diff --git a/README.md b/README.md index aacb9a70ff..e6fa7793d6 100644 --- a/README.md +++ b/README.md @@ -66,6 +66,7 @@ Provides additional types and type adjusted utilities for `typescript` - `Except`: Deprecated. Same as `Omit`. - `ExcludePropType`: excludes type `U` from properties in `T`. - `KeyofOptional`: `keyof` that works with `Record | undefined`. +- `KnownKeys`: extract known (defined) keys from type `T`. - `Omit`: From `T`, pick a set of properties whose keys are not in the union `K`. This is the opposite of `Pick`. - `PartialExcept`: Deprecated. Same as `PartialOmit`. - `PartialOmit`: makes the properties not specified in `U` becomes optional. diff --git a/src/KnownKeys.spec.ts b/src/KnownKeys.spec.ts new file mode 100644 index 0000000000..9ff1de7448 --- /dev/null +++ b/src/KnownKeys.spec.ts @@ -0,0 +1,39 @@ +import { assertType, KnownKeys } from '.' + +test('pick out only known keys', () => { + type A = { + a?: boolean, + b?: number, + [k: string]: any, + } + + const input: A = {} + const actual = getKnownKeys(input) + assertType<'a' | 'b'>(actual) +}) + +test('primitive type yields never', () => { + assertType.isNever(getKnownKeys(undefined)) + assertType.isNever(getKnownKeys(true)) + assertType.isNever(getKnownKeys(false)) + assertType.isNever(getKnownKeys(null)) + assertType.isNever(getKnownKeys('str')) + assertType.isNever(getKnownKeys(1)) + assertType.isNever(getKnownKeys({})) + assertType.isNever(getKnownKeys([])) +}) + +test('literal gets keys', () => { + assertType<'a'>(getKnownKeys({ a: 1 })) +}) + +test('empty record yields never', () => { + const x: Record = {} + const actual = getKnownKeys(x) + assertType.isNever(actual) +}) + + +function getKnownKeys(_value: T): KnownKeys { + return {} as any +} diff --git a/src/KnownKeys.ts b/src/KnownKeys.ts new file mode 100644 index 0000000000..92614715c8 --- /dev/null +++ b/src/KnownKeys.ts @@ -0,0 +1,7 @@ +// by Klaus Meinhardt @ajafff +// known from Gerrit Birkeland @Gerrit0 +// https://github.com/Microsoft/TypeScript/issues/25987#issuecomment-408339599 +// https://github.com/microsoft/TypeScript/issues/25987#issuecomment-441224690 +export type KnownKeys = { + [K in keyof T]: string extends K ? never : number extends K ? never : K +} extends { [_ in keyof T]: infer U } ? ({} extends U ? never : U) : never; diff --git a/src/index.ts b/src/index.ts index 92eca32ca4..61a9285105 100644 --- a/src/index.ts +++ b/src/index.ts @@ -21,6 +21,7 @@ export * from './JSONTypes'; export * from './KeyofOptional'; export * from './KeysWithDiffType'; export * from './KeyTypes'; +export * from './KnownKeys'; export * from './literalArray'; export * from './mapKey'; export * from './mapSeries';