I was trying to add type safety to some model i have and it seems to sometimes work in a weird way.
Code
exportenumFilterType{String='string',Number='number',Boolean='boolean'}exportinterfaceFilterTypeToLiteralTypeMap{[FilterType.String]: string;[FilterType.Number]: number;[FilterType.Boolean]: boolean;}exporttypeAllowedFilterTypeLiteralTypes=FilterTypeToLiteralTypeMap[FilterType];exporttypeValues<T>=T[keyofT];exporttypeFilterTypeFromLiteralType<TextendsAllowedFilterTypeLiteralTypes>=Exclude<Values<{[keyinFilterType]: FilterTypeToLiteralTypeMap[key]extendsT
? key
: never;}>,never>;exportinterfaceFilterable<TextendsAllowedFilterTypeLiteralTypes>{isFilterable: true;filterType: FilterTypeFromLiteralType<T>;}exportinterfaceNotFilterable{isFilterable: false;}exporttypeFilterableTrait<TextendsAllowedFilterTypeLiteralTypes>=|Filterable<T>|NotFilterable;What i did here is created an enum and mapped each entry to a literal type. That way when using the FilterableTrait interface it can be either Filterable or NotFilterable and if filterable the FilterType is decided based on the given type.
Some usages that work
// Errors correctlyexportconsta: FilterableTrait<string>={isFilterable: true,filterType: FilterType.Number};// Works correctlyexportconstb: FilterableTrait<string>={isFilterable: true,filterType: FilterType.String};exportconstc: FilterableTrait<string>={isFilterable: false,filterType: FilterType.String// Errors correctly};// Errors correctlyexportconstd: FilterableTrait<string>|FilterableTrait<number>={isFilterable: true,filterType: FilterType.Boolean};// Works correctlyexportconste: FilterableTrait<string>|FilterableTrait<number>={isFilterable: true,filterType: FilterType.Number};The problem starts when i do this
exportconstf: FilterableTrait<string>|FilterableTrait<number>={isFilterable: false,filterType: FilterType.Number// No error? Auto complete doesn't add this as an option but it compiles};A few notes here:
- If i change
Filterable to be filterType: FilterTypeFromLiteralType<string> instead of filterType: FilterTypeFromLiteralType<T> it works... it doesnt work just when i use the generic type. - I know i can use
exportconstg: FilterableTrait<string|number>={isFilterable: false,filterType: FilterType.Number};and it will work but my actual use case requires me to use something like
exportconsth:
|({type: '1'}&FilterableTrait<string>)|({type: '2'}&FilterableTrait<number>)={type: '2',isFilterable: true,filterType: FilterType.Number};Which means i can't use the above
Expected behavior:
Compilation error
Actual behavior:
Compiles successfully
Playground Link:http://www.typescriptlang.org/play/?ts=3.7-Beta&ssl=31&ssc=3&pln=17&pc=1#
I was trying to add type safety to some model i have and it seems to sometimes work in a weird way.
Code
What i did here is created an enum and mapped each entry to a literal type. That way when using the
FilterableTraitinterface it can be eitherFilterableorNotFilterableand if filterable theFilterTypeis decided based on the given type.Some usages that work
The problem starts when i do this
A few notes here:
Filterableto befilterType: FilterTypeFromLiteralType<string>instead offilterType: FilterTypeFromLiteralType<T>it works... it doesnt work just when i use the generic type.and it will work but my actual use case requires me to use something like
Which means i can't use the above
Expected behavior:
Compilation error
Actual behavior:
Compiles successfully
Playground Link:http://www.typescriptlang.org/play/?ts=3.7-Beta&ssl=31&ssc=3&pln=17&pc=1#