Skip to content

Instantly share code, notes, and snippets.

@OliverJAsh
Last active April 19, 2019 09:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save OliverJAsh/b35a3e54cd2168517a4f76d6a7fe0664 to your computer and use it in GitHub Desktop.
Save OliverJAsh/b35a3e54cd2168517a4f76d6a7fe0664 to your computer and use it in GitHub Desktop.
TypeScript `getProperty` for safe index lookups in records
{
// 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