Considere esta función:
function fn<T>(a: T, b: T[]): T {} Me gustaría inferir T de a , luego verificar b contra T . En cambio, TS infiere T tanto de a como de b . P.ej:
fn(1, [1, 'str']); Esto devuelve number | string Sin embargo, quiero que T se infiera como number , por lo que arrojaría un error como "número | la cadena no se puede asignar a número". es posible?
Podría proporcionar un tipo explícito:
declare function fnA<T>(a: T, b: (T extends T ? T : never)[]): T fnA<number>(1, [2, 'str']) // Type 'string' is not assignable to type 'number'.(2322)O hacer algo como:
declare function fnB<T>(a: T, b: (T extends T ? T : never)[]): T fnB(1, [1, 'str']); // Type 'string' is not assignable to type '1'.(2322) Esto obliga al compilador a tener que examinar el tipo de a para averiguar el tipo de b .
Pero esto parece inferir un tipo más específico que number , por lo que no funciona:
fnB(1, [1, 2]); // Type '2' is not assignable to type '1'.(2322) Creo que esto rompe algunos mecanografiados heurísticos sobre cuándo un tipo se amplía automáticamente a number o string , y cuándo no. Y es complicado para el mecanografiado saber qué tan estrictamente restringir ese tipo.
Sin embargo, funcionará bien si el primer argumento es un tipo más amplio como number :
const x: number = 1 fnB(x, [1, 2]); // fineO podría, nuevamente, proporcionar el tipo si no le gusta cómo se infirió:
fnB<number>(1, [1, 2]); // fineAunque es solo una idea, tal vez puedas usar HOF
declare const fn = <T,>(a: T) => (b:T): T fn(1)([1,'str']) // Argument of type '(string | number)[]' is not assignable to parameter of type 'number'.ts(2345)Pero como sugirió @alex, es mejor proporcionar un tipo explícito siempre que lo sepa
Hay un enfoque alternativo:
type Primitives = | string | number | bigint | boolean | symbol | null | undefined type BackwardInference<T, P=Primitives> = P extends any ? T extends P ? P : never : never; declare function fn<T>(a: T, b: BackwardInference<T>[]): T fn(1, [45]) // ok fn('str', ['hello']) // ok fn(42, ['str']) // expected error Debido a que TS infiere el tipo literal si el primer argumento es un primitivo, podemos perder un poco el rigor de la inferencia. Significa que cuando el primero sea literal 42 , el segundo argumento se esperará como number y no como 42