From 8c714d420fa4b16d8b92f35b06dfcaffe524be55 Mon Sep 17 00:00:00 2001 From: Martin Hochel Date: Wed, 16 Jun 2021 14:41:24 +0200 Subject: [PATCH] test(tools): add docs for type utils and cover those utils by tests --- tools/types.spec.ts | 31 ++++++++++++++++++++++++++++++ tools/types.ts | 46 +++++++++++++++++++++++++++++++++++++-------- 2 files changed, 69 insertions(+), 8 deletions(-) create mode 100644 tools/types.spec.ts diff --git a/tools/types.spec.ts b/tools/types.spec.ts new file mode 100644 index 00000000000000..e8c1a78735683d --- /dev/null +++ b/tools/types.spec.ts @@ -0,0 +1,31 @@ +import { KnownKeys, RemoveRecordIndexSignature } from './types'; + +describe(`types`, () => { + describe(`utils`, () => { + describe(`#KnownKeys`, () => { + it(`should get keys from record except index signatures`, () => { + type RecordWithIndexType = { one: number; two: string; [k: string]: unknown }; + + // $ExpectType 'one' | 'two' + type Test = KnownKeys; + + // @ts-expect-error - testing types + const assertion: Test = 'random'; + expect(assertion).toBeDefined(); + }); + }); + + describe(`#RemoveRecordIndexSignature`, () => { + it(`it should get record shape without index signatures`, () => { + type RecordWithIndexType = { one: number; two: string; [k: string]: unknown }; + + // $ExpectType { one: number; two: string; } + type Test = RemoveRecordIndexSignature; + + // @ts-expect-error - testing types + const assertion: Test = { one: 1, two: '2', fooBar: true }; + expect(assertion).toBeDefined(); + }); + }); + }); +}); diff --git a/tools/types.ts b/tools/types.ts index 8add9e60fed61c..07e73d2379da58 100644 --- a/tools/types.ts +++ b/tools/types.ts @@ -1,13 +1,9 @@ -type RemoveIndex> = Pick>; -type KnownKeys = { - [K in keyof T]: string extends K ? never : number extends K ? never : K; -} extends { [_ in keyof T]: infer U } - ? U - : never; - type TsOriginalCompilerOptions = import('typescript').CompilerOptions; interface CompilerOptions - extends Omit, 'module' | 'target' | 'jsx' | 'moduleResolution'> { + extends Omit< + RemoveRecordIndexSignature, + 'module' | 'target' | 'jsx' | 'moduleResolution' + > { module?: keyof typeof import('typescript').ModuleKind; target?: keyof typeof import('typescript').ScriptTarget; jsx?: 'none' | 'preserve' | 'react' | 'react-native' | 'react-jsx' | 'react-jsxdev'; @@ -32,3 +28,37 @@ export interface PackageJson { devDependencies?: Record; peerDependencies?: Record; } + +// =============== +// Type Utilities +// =============== + +/** + * Removes index signature `[key:string]: any` from Dictionary/Record + * + * @example + * + * ```ts + * type MapWithIndexType = { one: number; two: string; [k: string]: any; } + * // $ExpectType { one: number; two: string; } + * type Test = RemoveRecordIndexSignature + * ``` + */ +export type RemoveRecordIndexSignature> = Pick>; + +/** + * Get proper known keys from object which contains index type `[key:string]: any` + * + * @example + * + * ```ts + * type MapWithIndexType = { one: number; two: string; [k: string]: any; } + * // $ExpectType 'one' | 'two' + * type Test = KnownKeys + * ``` + */ +export type KnownKeys = { + [K in keyof T]: string extends K ? never : number extends K ? never : K; +} extends { [_ in keyof T]: infer U } + ? U + : never;