Last active
October 26, 2022 15:07
-
-
Save OliverJAsh/1acbcc951e3534694b3dace6be5ef5b3 to your computer and use it in GitHub Desktop.
TypeScript: infer function parameter as a tuple, not an array
This file contains hidden or 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
{ | |
declare const fn: <T>(fn: (t: T) => void, t: T) => void; | |
fn( | |
(t) => { | |
// $ExpectType [number, string] | |
// ❌ | |
// Actual: (string | number)[) | |
t; | |
}, | |
[1, 'foo'], | |
); | |
} | |
{ | |
declare const fn: <T extends any[]>(fn: (t: T) => void, t: T) => void; | |
fn( | |
(t) => { | |
// $ExpectType [number, string] | |
// ❌ | |
// Actual: (string | number)[) | |
t; | |
}, | |
[1, 'foo'], | |
); | |
} | |
// `const` assertions | |
{ | |
declare const fn: <T extends readonly any[]>( | |
fn: (t: T) => void, | |
t: T, | |
) => void; | |
fn( | |
(t) => { | |
// $ExpectType readonly [number, string] | |
// ✅ | |
t; | |
}, | |
[1, 'foo'] as const, | |
); | |
} | |
// Using new TS v4 syntax | |
// https://devblogs.microsoft.com/typescript/announcing-typescript-4-0/#variadic-tuple-types | |
{ | |
declare const fn: <T extends any[]>(fn: (t: T) => void, t: [...T]) => void; | |
fn( | |
(t) => { | |
// $ExpectType [number, string] | |
// ✅ | |
t; | |
}, | |
[1, 'foo'], | |
); | |
} | |
// Using a trick I found in a library, which I don't really understand… | |
// https://github.com/LeetCode-OpenSource/rxjs-hooks/blob/89c4b89265/src/type.ts#L1 | |
// https://github.com/LeetCode-OpenSource/rxjs-hooks/pull/16/files | |
// https://github.com/LeetCode-OpenSource/rxjs-hooks/commit/fe62b52a1303024a68ac20757de62949c519c06a | |
{ | |
type RestrictArray<T> = T extends any[] ? T : []; | |
declare const fn: <T>(fn: (t: T) => void, t: RestrictArray<T>) => void; | |
fn( | |
(t) => { | |
// $ExpectType [number, string] | |
// ✅ | |
t; | |
}, | |
[1, 'foo'], | |
); | |
} | |
// https://twitter.com/TitianCernicova/status/1299324925384241155 | |
{ | |
declare const fn: <T extends [any] | any[]>(fn: (t: T) => void, t: T) => void; | |
fn( | |
(t) => { | |
// $ExpectType [number, string] | |
// ✅ | |
t; | |
}, | |
[1, 'foo'], | |
); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment