Unfortunately, I do not have the TS 2.6.2 compiler, so I canβt double check if this works. And since this involves adding an existing type, this is not my favorite solution (a solution of 2.8 with conditional types proposed by @Motti is definitely a way to go).
, . , FancyType - merge . :
interface FancyType {
'**fancyBrand**'?: never
}
, FancyType , **fancyBrand** never. , , FancyType .
. ValueOf<T> :
type ValueOf<T> = T[keyof T];
, ValueOf<{a: string, b: number}> string | number. Diff :
type Diff<T extends string, U extends string> =
({ [K in T]: K } & { [K in U]: never } & { [k: string]: never })[T];
, Diff<'a'|'b'|'c', 'a'> 'b'|'c'.
, FancyKeys<T>, , T, FancyType:
type FancyKeys<T> = Diff<keyof T, ValueOf<
{ [K in keyof T]: (T[K] & { '**fancyBrand**': K })['**fancyBrand**'] }>>
FancyKeys<Something> 'value1'|'value2'|'value3':
function someFunction(key: FancyKeys<Something>) {
}
someFunction("id");
someFunction("value2");
FancyKeys<T> T , T, '**fancyBrand**', . FancyType '**fancyBrand**' never undefined. , ( '**fancyBrand**'), .
Something {id: 'id', name: 'name', value1: undefined, value2: undefined, value3: undefined}. ValueOf<T> , 'id'|'name'|undefined. - , Diff<keyof Something, U> 'value1'|'value2'|'value2'... , undefined Diff<>, . , **fancyBrand**, FancyType, , , ( , ).
, , yucky, , . , , . !