Last active
April 19, 2019 09:26
-
-
Save OliverJAsh/b35a3e54cd2168517a4f76d6a7fe0664 to your computer and use it in GitHub Desktop.
TypeScript `getProperty` for safe index lookups in records
This file contains 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
{ | |
// TS doesn't return the correct type for index lookups. It returns `T` when it might actually be `T | |
// | undefined`. These helpers give us the correct type. | |
// https://github.com/Microsoft/TypeScript/issues/13778 | |
type IndexLookup<Key extends string, V, K extends Key> = string extends Key | |
? Record<Key, V>[K] | undefined | |
: Record<Key, V>[K]; | |
// $ExpectType string | undefined | |
type Test1 = IndexLookup<string, string, string>; | |
// $ExpectType string | undefined | |
type Test2 = IndexLookup<string, string, 'foo'>; | |
// $ExpectType string | |
type Test3 = IndexLookup<'foo', string, 'foo'>; | |
const getProperty = <Key extends string, V, K extends Key>( | |
obj: Record<Key, V>, | |
key: K, | |
): IndexLookup<Key, V, K> => obj[key] as any; | |
{ | |
// If we don't know which keys exist, it should return undefined. | |
declare const myRecord: Record<string, string>; | |
// $ExpectType string | undefined | |
const result = getProperty(myRecord, 'whatever'); | |
} | |
{ | |
// If we do know which keys exist, it should not return undefined. | |
declare const myRecord: Record<'foo', string>; | |
// $ExpectType string | |
const result = getProperty(myRecord, 'foo'); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment