Почему возвращаемый интерфейс из функции не работает как нужно?

Обожаю статическую типизацию, но ненавижу TypeScript.
В общем, сами посмотрите пример глюка

interface someInterface {
    test1?: string,
    test2?: string,
}

type someType = (() => someInterface) | someInterface

const someFunc = (param: someType) => 'here we go';

// Error: test3 doesn't exist
someFunc({ test1: '', test2: '', test3: '' });

// NOT Error
someFunc(() => (
    { test1: '', test2: '', test3: '' }
));

В функцию someFunc можно передавать интерфейс или функцию, которая возвращает интерфейс.
Когда мы передаём в качестве аргумента просто интерфейс, то все работает как нужно, но когда функцию, то происходит какой-то глюк. То-есть, можно добавлять любые свойства и TypeScript не будет ругаться.

Почему это происходит?


Ответы (2 шт):

Автор решения: Кирилл Панишев

Если написать так, то проверит

interface someInterface {
    test1?: string,
    test2?: string,
}

type someType = (() => someInterface) | someInterface

const someFunc = (param: someType) => 'here we go';

// Error: test3 doesn't exist
someFunc({ test1: '', test2: '', test3: '' });

// NOT Error
someFunc(():someInterface => ({ test1: '', test2: '', test3: '' }));
→ Ссылка
Автор решения: Grundy

При работе с литералами объекта, typescript строго проверяет соответствие интерфейсу, чтобы исключить разные опечатки.

Поэтому в первом случае происходит ошибка: литерал

{ test1: '', test2: '', test3: '' }

содержит лишнее поле, которого нет в интерфейсе.


Что происходит во втором случае: в качестве параметра передается функция

() => (
    { test1: '', test2: '', test3: '' }
)

Так как прямо не указан тип возвращаемого значения, он выводится автоматически. В данном случае тип возвращаемого значения будет

{
    test1: string;
    test2: string;
    test3: string;
}

Далее идет проверка, можно ли объект данного типа присвоить переменной с типом someInterface - и это действительно возможно, так как в типе присутствуют все обязательные поля. Поэтому никакой ошибки в этом случае быть и не должно.

→ Ссылка