Typescript strictNullChecks проверяет функции

С включенным --strictNullChecks tsc, похоже, не может сделать вывод, что необязательное свойство не является неопределенным, если проверка происходит в отдельной функции. (См. пример, потому что у меня возникли проблемы с четкой формулировкой).

Учитывая интерфейс с необязательным свойством, например

interface Foo {
    bar?: {
        baz: string;
    };
}

Компилируется следующий код:

//compiles
function doStuff(foo: Foo) {
    if (foo.bar === undefined) {
        throw new Error("foo.bar must be defined");
    }
    foo.bar.baz;
}

И этот код не работает, потому что tsc считает, что foo.bar может быть неопределенным:

//does not compile, foo.bar can be undefined
function doStuff2(foo: Foo) {
    validateFoo(foo);
    foo.bar.baz;
}

function validateFoo(foo: Foo) {
    if (foo.bar === undefined) {
        throw new Error("foo.bar must be defined");
    }
}

Почему это? Есть ли способ пометить функцию как вещь, которая может проверять неопределенность и нуль? Я хотел бы избежать foo.bar!.baz, если это возможно. В этом примере легко встроить if/throw, но если у Foo есть несколько необязательных свойств, которые необходимо проверить в нескольких функциях, они повторяются.


person martiansnoop    schedule 14.11.2016    source источник
comment
здесь у меня работает - jsfiddle.net/of5ja33v   -  person gkb    schedule 14.11.2016
comment
@gkb есть ли способ указать в jsfiddle, какая версия tsc используется, а также использовать флаги компилятора? strictNullChecks по умолчанию имеет значение false и есть только в typescript 2.0+.   -  person martiansnoop    schedule 15.11.2016
comment
извините, я совсем пропустил strictNullChecks для tsc ‹ 2.0+.   -  person gkb    schedule 15.11.2016


Ответы (1)


Почему это?

Вы можете представить себе, что TypeScript пытается встроить функцию для этого, но чтобы затем получить точный результат, вам нужно также встроить каждую функцию, которую вызывает validateFoo — это может быть сколь угодно глубоким.

На самом деле существует целое обсуждение этого здесь, в системе отслеживания проблем TypeScript.

Есть ли способ пометить функцию как вещь, которая может проверять неопределенность и нуль?

Вроде того, есть предикаты типа, которые представляют собой функции, которые сообщают TypeScript тип параметра, если функция возвращает true.

function validateFoo(foo: Foo): foo is { bar: { baz: string } } {
    if (foo.bar === undefined) {
        throw new Error("foo.bar must be defined");
    }
    return true;
}

Вы можете использовать его следующим образом:

function doStuff(foo: Foo) {
    if (!validateFoo(foo)) {
        throw foo;
    }
    foo.bar.baz;
}
person Daniel Rosenwasser    schedule 14.11.2016