Weboldal keresés

redux - Miért dob Typescript hibaüzenetet: A tulajdonság nem létezik a típuson?


Két kódpéldát készítettem. Az egyetlen különbség közöttük az, hogy milyen kifejezést adok át a switch operátornak.

Az első esetben egy objektum tulajdonságát használom. És ez jól működik.

Egy második esetben létrehozok egy type változót. És a TypeScript hibajelzést dob:

A(z) 'name' tulajdonság nem létezik az 'Action' típuson.

A 'name' tulajdonság nem létezik a '{ type: "reset"; }' típuson.

Miért történik ez?

Az action.type objektumtulajdonság és a type változó ugyanazon a típusten 'reset' | 'update'.

interface State {
    name: string;
    cars: any[];
}

type Action = { type: 'reset' } | { type: 'update', name: string };

function reducer(state: State, action: Action): State {
    switch (action.type) {
        case 'update':
            return { ...state, name: action.name };
        case 'reset':
            return {...state, cars: [] };
        default:
            throw new Error();
    }
}

interface State {
    name: string;
    cars: any[];
}

type Action = { type: 'reset' } | { type: 'update', name: string };

function reducer(state: State, action: Action): State {
    /**
    * Create a 'type' variable
    */
    const { type } = action;

    switch (type) {
        case 'update':
            return { ...state, name: action.name };
    /**
    * Typescript will throw an error message
    * Property 'name' does not exist on type 'Action'.
    * Property 'name' does not exist on type '{ type: "reset"; }'.
    */
        case 'reset':
            return {...state, cars: [] };
        default:
            throw new Error();
    }
}

Kép leírása

Válasz #1

Alapvetően a TypeScript nem követi a kapcsolatot a action és a type változók típusai között; amikor a type típusa leszűkül (például egy switch utasítás case ágában), az nem szűkíti automatikusan a action típusát sem.

A const { type }=action; hozzárendelésnél a fordító a type: Action['type'] típust következteti ki, ami éppen 'reset' | 'update'. Később a case kifejezés nem szűkíti az action típusát, mert az action-ön nem történt típusvédő ellenőrzés.

Ahhoz, hogy ez úgy viselkedjen, ahogyan szeretnéd, a fordítónak be kellene vezetnie egy típusváltozót T extends Action['type'] és ki kellene következtetnie type: T-t, miközben egyidejűleg szűkítené az action típusát : Action & { type: T }-re. Ezután, amikor a type típusa szűkül, maga a T-nek is szűkülnie kellene, így a hatás továbbterjedne az action típusára, ami T-t érintene.

Új típusváltozó bevezetése így minden változó hozzárendelésnél, valamint a típusváltozók felső határainak vezérlési áramlással történő szűkítése nagymértékben bonyolítaná a típusellenőrző algoritmust. Ez a becsült típusokat is jelentősen bonyolítaná, így a felhasználók számára nehezebben érthetővé válnának; ezért ésszerű, hogy a Typescript ezt nem teszi. Általánosságban elmondható, hogy a típusellenőrzők nem bizonyítanak minden bizonyítható tulajdonságot a kódodról, és ez egy példa erre.

Válasz #2

Amikor az érvelésre hivatkozol, az képes a típust az egész objektumból következtetni, de amikor egy konstansot hozol létre, a típust egyszerűen "reset" | "update" típusra korlátozod, és az Action objektumtípus egyéb részei elvesznek.

Kapcsolódó cikkek