Skip to content

Instantly share code, notes, and snippets.

@OliverJAsh

OliverJAsh/foo.ts

Last active Aug 29, 2020
Embed
What would you like to do?
TypeScript: infer function parameter as a tuple, not an array
{
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
You can’t perform that action at this time.