javascript - Hur härleder Typescript generiska typer och varför fungerar det inte i ett fall?
Varför finns det ett Typescript-fel med f2(f1)? För mig verkar det som att f2, f3 och f4 har samma typer. Det är bara deklarerat olika. Var är skillnaden mellan f4 och f2 eller f3?
Jag har följande exempel:
Typescript-lekplats
Kod :
interface FullType {
id: string;
order_no: number;
}
interface OrderType {
[key: string]: any;
order_no: number;
}
const f1 = (d1: FullType): Promise<FullType> => {
return new Promise(() => {
return d1;
});
};
function f2<Type extends OrderType, Fn extends (t: Type) => Promise<Type>>(
f: Fn,
): void {
//
}
function f3<Type extends OrderType>(f: (t: Type) => Promise<Type>): void {
//
}
function f4<Type1 extends Type2, Type2 extends OrderType>(
f: (item: Type1) => Promise<Type1>,
): void {
//
}
f2(f1); // why is here a warning
f3(f1);
f4(f1);
Svar #1
I TypeScript fungerar generics oftast utan problem, men när du börjar använda redan utökade generiska typer för att definiera nya generiska typer som också kommer att utökas - är det här problemen uppstår. Generellt sett anses Generiska Begränsningar (t.ex. <T>) i TypeScript inte vara typer som kan härledas ytterligare, vilket betyder att medan det är ofarligt att utöka en utökad typ som du har i f4, är det problematiskt att utöka en nydefinierad typ som också använder generics:
f4 är helt okej:
<Type1 extends Type2, Type2 extends OrderType>f3 är också bra eftersom det inte utökar typen för att definiera callbacken utan istället skapar den direkt:
f: (t: Type) => Promise<Type>f2 är där problemet börjar uppstå eftersom parametertypen använder en utökad generisk typ som också använder utökade värden. Detta gör att typen standardiseras tillbaka till OrderType och eftersom FullType inte direkt är lika med OrderType observerar du det felet:
Fn extends (t: Type) => Promise<Type>Detta kan ytterligare illustreras genom att definiera detta i en separat typ:
type CustomCallback<T> = (t: T) => Promise<T>;
// This will work just fine
function f2<Type extends OrderType>(f: CustomCallback<Type>): void {
//
}
// this will not
function f2<Type extends OrderType, paramType extends CustomCallback<Type>>(f: paramType): void {
//
}
Här är Playground-länken.
Jag måste dessutom nämna att nyckelordet extends extraherar alla kända egenskaper från en typ och tillåter att andra värden används på grund av indexsignaturen [key: string]: any; som är definierad i OrderType, därför är detta anledningen till att inga fel visas för f3 och f4. Men om du använde en direkt typ i någon av dem kommer du att börja se en varning eftersom FullType inte är lika med OrderType.
function f3(f: (t: OrderType) => Promise<OrderType>): void {
//
}
f3(f1); // warning
För att sammanfatta allt, som en generell regel, försök att undvika att utvidga generiska typer som redan använder utökade variabler.
