From 33a93d89f3376e91bb24831ded0ced6e547c204c Mon Sep 17 00:00:00 2001 From: Emiya Date: Mon, 18 Mar 2024 16:52:04 +0800 Subject: [PATCH 1/4] fix SetParameterType --- .github/workflows/main.yml | 2 +- source/set-parameter-type.d.ts | 71 +++++++++++++++++++++++++++------- test-d/set-parameter-type.ts | 12 ++++-- 3 files changed, 67 insertions(+), 18 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 78cddd394..f0e5fc499 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -37,4 +37,4 @@ jobs: node-version: 18 - run: npm install - run: npm install typescript@${{ matrix.typescript-version }} - - run: npx tsc + - run: npx test diff --git a/source/set-parameter-type.d.ts b/source/set-parameter-type.d.ts index 1add7b8fa..67e8d5ffc 100644 --- a/source/set-parameter-type.d.ts +++ b/source/set-parameter-type.d.ts @@ -1,17 +1,53 @@ import type {IsUnknown} from './is-unknown'; +import type {StaticPartOfArray} from './internal'; +import type {UnknownArray} from './unknown-array'; /** -Create a tuple that replaces the given `Tuple`'s elements with the given `Record_`'s values at the given indices. +Create a array that replaces the given `TArray`'s elements with the given `TObject`'s values at the given indices. + +`TArray` and `TObject` supports tailing spread array like `[string, ...boolean[]]`, but not support `[string, ...boolean[], number]`. + +@example: +```ts +// object +type A = MergeObjectToArray<[string, number], {0: boolean}>; +//=> [boolean, number] + +// array +type B = MergeObjectToArray<[string, number], [boolean]>; +//=> [boolean, number] + +// tailing spread array +type C = MergeObjectToArray<[string, ...boolean[]], {1: number}>; +//=> [string, ...number[]] + +type D = MergeObjectToArray<[string, ...boolean[]], [number, ...string[]]>; +//=> [number, ...string[]] +``` */ -type MergeObjectToTuple> = { - [K in keyof Tuple]: Record_ extends Record - // Handle object case like `{0: string, 1: number}` - ? K extends `${infer NumberK extends number}` - ? NumberK extends keyof Record_ ? Record_[K] : Tuple[K] - : never // Should not happen - // Handle tuple case like `[string, number]` - : K extends keyof Record_ ? Record_[K] : Tuple[K] -}; +type MergeObjectToArray = + // If `TObject` is an array like `[0, 1, 2]` + TObject extends UnknownArray + // If `TObject` is a variable length array, we should use `TObject`'s type as the result type. + ? number extends TObject['length'] + ? TObject + : { + [K in keyof TArray]: K extends keyof TObject ? TObject[K] : TArray[K] + } + : TObject extends object + // If `TObject` is a object witch key is number like `{0: string, 1: number}` + ? { + [K in keyof TArray]: + K extends `${infer NumberK extends number}` + ? NumberK extends keyof TObject ? TObject[NumberK] : TArray[K] + : number extends K + // If array key `K` is `number`, means it's a rest parameter, we should set the rest parameter type to corresponding type in `TObject`. + // example: `MergeObjectToParamterArray<[string, ...boolean[]], {1: number}>` => `[string, ...number[]]` + ? StaticPartOfArray['length'] extends keyof TObject + ? TObject[StaticPartOfArray['length']] + : TArray[K] + : never + } : never; /** Create a function that replaces some parameters with the given parameters. @@ -39,7 +75,7 @@ Use-case: ``` import type {SetParameterType} from 'type-fest'; -type HandleMessage = (data: Data, message: string) => void; +type HandleMessage = (data: Data, message: string, ...arguments: any[]) => void; type HandleOk = SetParameterType; //=> type HandleOk = (data: SuccessData, message: 'ok') => void; @@ -51,6 +87,15 @@ type HandleError = SetParameterType; //=> type HandleWarn = (data: Data, message: 'warn') => void; + +// Could change rest parameter type. +// Way 1: input full parameter type. +type HandleLog = SetParameterType; +//=> type HandleLog = (data: Data, message: 'log', ...arguments: string[]) => void; + +// Way 2: input rest parameter type by Object index. +type HandleLog2 = SetParameterType; +//=> type HandleLog2 = (data: Data, message: string, ...arguments: string[]) => void; ``` @category Function @@ -62,7 +107,7 @@ export type SetParameterType unknown, P ext // If a function did not specify the `this` fake parameter, it will be inferred to `unknown`. // We want to detect this situation just to display a friendlier type upon hovering on an IntelliSense-powered IDE. IsUnknown extends true - ? (...arguments_: MergeObjectToTuple) => ReturnType - : (this: ThisArg, ...arguments_: MergeObjectToTuple) => ReturnType + ? (...arguments_: MergeObjectToArray) => ReturnType + : (this: ThisArg, ...arguments_: MergeObjectToArray) => ReturnType ) : Fn; // This part should be unreachable diff --git a/test-d/set-parameter-type.ts b/test-d/set-parameter-type.ts index dde849506..2ce95816d 100644 --- a/test-d/set-parameter-type.ts +++ b/test-d/set-parameter-type.ts @@ -1,5 +1,5 @@ import {expectType} from 'tsd'; -import {type SetParameterType} from '../index'; +import type {SetParameterType} from '../index'; function fn(_a: number, _b: string, _c: Object, ..._arguments: boolean[]) { return null; @@ -27,9 +27,13 @@ expectType<(a: string, b: boolean, c: Object, ...args: boolean[]) => null>(test3 test3('1', true, {}, true); // Test `...args` parameter -declare const test4: SetParameterType; -expectType<(a: number, b: string, c: Object, ...args: string[]) => null>(test4); -test4(1, '1', {}, '1'); +declare const testargs: SetParameterType; +expectType<(a: number, b: string, c: Object, ...args: string[]) => null>(testargs); +testargs(1, '1', {}, '1'); + +declare const testargs2: SetParameterType; +expectType<(a: string, b: number, c: number, ...args: boolean[]) => null>(testargs2); +testargs2('1', 1, 1, true); // Test arrow function declare const test5: SetParameterType; From 3bc14646d441ba44eed0f9f080e62d5ac0bacd86 Mon Sep 17 00:00:00 2001 From: Emiya Date: Mon, 18 Mar 2024 16:53:22 +0800 Subject: [PATCH 2/4] fix --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index f0e5fc499..7e0a3958d 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -37,4 +37,4 @@ jobs: node-version: 18 - run: npm install - run: npm install typescript@${{ matrix.typescript-version }} - - run: npx test + - run: npm test From 77fbf5c744daa54c9392bc34fa2ba3ae8fd6c05d Mon Sep 17 00:00:00 2001 From: Sindre Sorhus Date: Mon, 18 Mar 2024 19:31:46 +0700 Subject: [PATCH 3/4] Update set-parameter-type.d.ts --- source/set-parameter-type.d.ts | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/source/set-parameter-type.d.ts b/source/set-parameter-type.d.ts index 67e8d5ffc..e030f2b9a 100644 --- a/source/set-parameter-type.d.ts +++ b/source/set-parameter-type.d.ts @@ -3,9 +3,9 @@ import type {StaticPartOfArray} from './internal'; import type {UnknownArray} from './unknown-array'; /** -Create a array that replaces the given `TArray`'s elements with the given `TObject`'s values at the given indices. +Create an array that replaces the given `TArray`'s elements with the given `TObject`'s values at the given indices. -`TArray` and `TObject` supports tailing spread array like `[string, ...boolean[]]`, but not support `[string, ...boolean[], number]`. +`TArray` and `TObject` supports tailing spread array like `[string, ...boolean[]]`, but does not support `[string, ...boolean[], number]`. @example: ```ts @@ -84,16 +84,17 @@ type HandleOk = SetParameterType; type HandleError = SetParameterType; //=> type HandleError = (data: ErrorData, message: 'error') => void; -// Could change single parameter type. +// Change single parameter type. type HandleWarn = SetParameterType; //=> type HandleWarn = (data: Data, message: 'warn') => void; -// Could change rest parameter type. -// Way 1: input full parameter type. +// Change rest parameter type. + +// Way 1: Input full parameter type. type HandleLog = SetParameterType; //=> type HandleLog = (data: Data, message: 'log', ...arguments: string[]) => void; -// Way 2: input rest parameter type by Object index. +// Way 2: Input rest parameter type by Object index. type HandleLog2 = SetParameterType; //=> type HandleLog2 = (data: Data, message: string, ...arguments: string[]) => void; ``` From 64651216b7ea228066024fe53ec000be81e8c8b7 Mon Sep 17 00:00:00 2001 From: Emiya Date: Mon, 18 Mar 2024 21:48:45 +0800 Subject: [PATCH 4/4] revert workflow --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 7e0a3958d..78cddd394 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -37,4 +37,4 @@ jobs: node-version: 18 - run: npm install - run: npm install typescript@${{ matrix.typescript-version }} - - run: npm test + - run: npx tsc