- Notifications
You must be signed in to change notification settings - Fork 13.2k
Closed
Description
TypeScript Version: 2.8.0-dev.20180216
Code
// Type-level filters to extract just the required or optional properties of a type// Defns from https://github.com/Microsoft/TypeScript/pull/21919#issuecomment-365491689typeRequiredPropNames<T>={[PinkeyofT]: undefinedextendsT[P] ? never : P}[keyofT];typeOptionalPropNames<T>={[PinkeyofT]: undefinedextendsT[P] ? P : never}[keyofT];typeRequiredProps<T>={[PinRequiredPropNames<T>]: T[P]};typeOptionalProps<T>={[PinOptionalPropNames<T>]: T[P]};// Some object types with different numbers of propstypeP2={a: string,b: number};// Two propstypeP1={a: string};// One proptypeP0={};// No props// Let's extract only the required properties of P0, P1, and P2typeP2Names=RequiredPropNames<P2>;// P2Names = "a" | "b" ✓😊typeP1Names=RequiredPropNames<P1>;// P1Names = "a" ✓😊typeP0Names=RequiredPropNames<P0>;// P0Names = any ?😕typeP2Props=RequiredProps<P2>;// P2Props ={a: string; b: number} ✓😊typeP1Props=RequiredProps<P1>;// P1Props ={a: string} ✓😊typeP0Props=RequiredProps<P0>;// P0Props ={[x: string]: any } ?😕Expected behavior:P0Names = never and P0Props ={}
Actual behavior:P0Names = any and P0Props ={[x: string]: any}
Notes:
@ahejlsberg helpfully came up with the RequiredProps and OptionalProps definitions above from a question I asked in #21919. They work great except when T ={}
Not 100% sure if this is a bug or not, but it's definitely counterintuitive. RequiredProps works for any object type except the empty one, when a string indexer suddenly appears. It certainly breaks the semantic expectations of RequiredProps.
Workaround:
The following version of RequiredPropNames achieves the expected behaviour by singling out the {} case:
typeRequiredPropNames<T>=keyofTextendsnever ? never : {[PinkeyofT]: undefinedextendsT[P] ? never : P}[keyofT];Metadata
Metadata
Assignees
Labels
No labels