Last active
January 22, 2023 22:46
-
-
Save fabiosantoscode/9ccbf3f02732de6cf5954d5a63600f89 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
type MyTypeNames = { | |
'string': string, | |
'number': number, | |
} | |
type MyKey = { | |
readonly type: keyof MyTypeNames | |
readonly name: string | |
} | |
type MyKeys = ReadonlyArray<MyKey> | |
type AsOne<KeyArr extends MyKeys> = | |
KeyArr extends readonly [ | |
{ readonly type: infer GivenType extends keyof MyTypeNames, name: (infer Name extends string) }, | |
...infer RestKeys extends MyKeys | |
] | |
// We have a [{ type, name }, ...RestKeys]. Generate 1-key object and recurse to rest | |
? { [name in Name]: MyTypeNames[GivenType] } & AsOne<RestKeys> | |
: KeyArr extends readonly [] | |
? {} | |
: 'this type should not be reached because KeyArr is always an array' | |
const xx = [{ | |
type: 'string', | |
name: 'firstName' | |
}, { | |
type: 'string', | |
name: 'lastName' | |
}, { | |
type: 'number', | |
name: 'age' | |
}] as const | |
const x: AsOne<typeof xx> = { | |
firstName: 'somestr', | |
lastName: 'otherstr', | |
age: 123 | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const str = Symbol('MyType.String') | |
const num = Symbol('MyType.Number') | |
type MyKeys = ReadonlyArray<{ | |
readonly type: typeof str | |
readonly name: string | |
} | { | |
readonly type: typeof num | |
readonly name: string | |
}> | |
const xx = ([{ | |
type: str, | |
name: 'firstName' | |
}, { | |
type: str, | |
name: 'lastName' | |
}, { | |
type: num, | |
name: 'age' | |
}]as const) satisfies MyKeys | |
type AsOne<KeyArr extends MyKeys> = KeyArr extends readonly [infer T, ...infer T2 extends MyKeys] | |
? ( | |
// We have a [T, ...T2]. Look at T and generate the correct one-key object | |
T extends { readonly type: typeof str, name: (infer Name extends string) } | |
? ({ [name in Name]: string } & AsOne<T2>) : | |
T extends { readonly type: typeof num, name: (infer Name extends string) } | |
? ({ [name in Name]: number } & AsOne<T2>) | |
: 'not sure what <type> is' | |
) : KeyArr extends readonly [] | |
? {} | |
: 'this type should not be reached because KeyArr is always an array' | |
const x: AsOne<typeof xx> = { | |
firstName: 'somestr', | |
lastName: 'otherstr', | |
age: 123 | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment