Типы объединения: Typescript жалуется, что функции не хватает конечного оператора возврата, а тип возвращаемого значения не включает undefined. (2366)

Это мой код. У меня есть объединение типа CellType. Я предполагаю, что функция никогда не будет вызываться с null, ничем, undefined или simular.

Я не хочу иметь какое-либо предложение else или окончательный оператор возврата, так как я знаю, что все случаи обрабатываются. Но почему-то мне чего-то не хватает. Я играл с флагами. Я получаю предупреждение

«В функции отсутствует конечный оператор возврата, а тип возвращаемого значения не включает 'undefined'. (2366)» для возвращаемого значения CellType.

class Empty {
};

class MyError  {
    type!: number;
}

type CellType = number | string | boolean | Empty | MyError;

function plusOne(v: CellType): CellType {
    if (typeof v === 'number') {
        return v+1;
    }
    if (typeof v === 'string') {
        return -1;
    }
    if (typeof v === 'boolean') {
        return -1;
    }        
    if (v instanceof Empty) { return 1; }
    if (v instanceof MyError) { return v; }
    // return { 'type':-1}
}

console.log(plusOne(10));
console.log(plusOne("hej"));

площадка Link


person mattias    schedule 24.03.2020    source источник


Ответы (1)


Вы хотите, чтобы машинописный текст знал, что вы рассмотрели каждый случай; это называется «проверка полноты», и это описано в документации TypeScript.

В документации рекомендуется выбрать один из двух подходов:

Первый - скомпилировать с --strictNullChecks и убедиться, что каждая функция, в которой вы хотите проверить полноту, аннотирована явным типом возвращаемого значения. На практике это непрактично для большинства кодовых баз.

Второй - добавить небольшую функцию в библиотеку под названием assertNever:

function assertNever(x: never): never {
    throw new Error("Unexpected object: " + x);
}

Затем в вашем коде используйте assertNever, чтобы указать, что все возможные случаи должны быть рассмотрены, например:

function plusOne(v: CellType): CellType {
    if (typeof v === 'number') {
        return v+1;
    }
    if (typeof v === 'string') {
        return -1;
    }
    if (typeof v === 'boolean') {
        return -1;
    }        
    if (v instanceof Empty) { return 1; }
    if (v instanceof MyError) { return v; }
    return assertNever(v);
}

Это приведет к ошибке компиляции, если вы не рассмотрели все возможные случаи к моменту достижения assertNever.

person jacobm    schedule 24.03.2020
comment
Дополнительная информация: эта конкретная проблема является ограничением дизайна (см. microsoft / TypeScript # 17358) . Обратите внимание, что в TS3.7 и выше вам не нужно ничего return, как в return assertNever(v); вы можете просто назвать это ... так что измените его на assertNever(v); - person jcalz; 24.03.2020
comment
Добавление assert никогда не решало эту проблему. Кроме того, Empty должен быть определен как, поскольку класс без каких-либо полей делает plusOne ({}) в порядке, чего не должно быть. class Empty {__kind: Empty; constructor () {this .__ kind = Empty}}; var empty: Empty = new Empty () - person mattias; 26.03.2020