Ce face strictFunctionTypes
Când pui o funcție într-o variabilă cu alt tip de funcție, parametrii trebuie să se potrivească. O funcție care cere un Caine nu poate fi folosită acolo unde se va trimite orice Animal: ar putea primi o pisică și ar apela latra(). Fără opțiune, TypeScript acceptă potrivirea în ambele sensuri („bivarianță”); cu strictFunctionTypes, o respinge.
Verificarea se aplică tipurilor scrise ca funcție ((a: Animal) => void, proprietăți cu tip de funcție). Metodele declarate cu sintaxa de metodă (trateaza(a: Animal): void) rămân bivariante, ca să nu se strice tipuri vechi precum Array.
Implicit este false, dar devine true când strict este true.
Parametri
| Parametru | Descriere |
|---|---|
true |
Activează verificarea. |
false |
Dezactivează verificarea, chiar dacă "strict": true. |
(lipsă) |
Ia valoarea lui strict: activă dacă strict este true, altfel inactivă. |
Exemple
Exemplul 1: O funcție prea pretențioasă
plimba cere un Caine, dar variabila f promite că primește orice Animal. La rulare, f({ nume: "Rex" }) ar apela o metodă care nu există.
// tsconfig.json
{
"compilerOptions": {
"strictFunctionTypes": true
}
}
// index.ts
type Animal = { nume: string };
type Caine = Animal & { latra(): void };
function plimba(c: Caine) {
c.latra();
}
const f: (a: Animal) => void = plimba;
f({ nume: "Rex" });
Rezultat (tsc 5.9)
$ npx tsc --noEmit
index.ts(8,7): error TS2322: Type '(c: Caine) => void' is not assignable to type '(a: Animal) => void'.
Types of parameters 'c' and 'a' are incompatible.
Type 'Animal' is not assignable to type 'Caine'.
Property 'latra' is missing in type 'Animal' but required in type '{ latra(): void; }'.
Exemplul 2: Metodă față de proprietate cu tip de funcție
Aceeași atribuire trece pentru CuMetoda (sintaxă de metodă, bivariantă) și dă eroare doar pentru CuProprietate (linia 8). De aceea, în tipurile proprii, proprietățile cu tip de funcție sunt mai sigure.
// tsconfig.json
{
"compilerOptions": {
"strictFunctionTypes": true
}
}
// index.ts
type Animal = { nume: string };
type Caine = Animal & { latra(): void };
interface CuMetoda { trateaza(a: Animal): void }
interface CuProprietate { trateaza: (a: Animal) => void }
const m: CuMetoda = { trateaza(c: Caine) { c.latra(); } };
const p: CuProprietate = { trateaza: (c: Caine) => c.latra() };
console.log(m, p);
Rezultat (tsc 5.9)
$ npx tsc --noEmit
index.ts(8,28): error TS2322: Type '(c: Caine) => void' is not assignable to type '(a: Animal) => void'.
Types of parameters 'c' and 'a' are incompatible.
Type 'Animal' is not assignable to type 'Caine'.
Property 'latra' is missing in type 'Animal' but required in type '{ latra(): void; }'.
Exemplul 3: Sensul corect: funcția acceptă mai mult
O funcție care primește orice Animal poate fi folosită acolo unde se trimit doar câini. Asta este mereu sigur.
type Animal = { nume: string };
type Caine = Animal & { rasa: string };
const prezinta = (a: Animal) => console.log(`Acesta este ${a.nume}`);
const pentruCaini: (c: Caine) => void = prezinta;
pentruCaini({ nume: "Rex", rasa: "ciobănesc" });
Rezultat
Acesta este Rex
Greșeli frecvente
- Să crezi că eroarea este greșită pentru că „un câine este un animal”. Regula e inversă pentru parametri: funcția trebuie să accepte cel puțin tot ce i se poate trimite.
- Să declari callback-urile din interfețe ca metode ca să scapi de eroare. Pierzi verificarea; schimbă tipul parametrului.
Comenzi înrudite
strict: Pornește dintr-o singură mișcare toate verificările stricte de tipuri (strictNullChecks, noImplicitAny și celelalte).strictBindCallApply: Verifică argumentele trimise prin bind, call și apply după tipurile funcției originale.noImplicitAny: Dă eroare când TypeScript nu poate deduce un tip și ar folosi în tăcere any (de obicei la parametrii fără tip).