#typescript #types #null #nullable #typescript-types
#typescript #типы #null #nullable #typescript-типы
Вопрос:
Рассмотрим следующий абстрактный класс:
export abstract class Foo {
abstract bar(param: string | null): string
}
Изменение параметра на ненулевой в конкретной реализации не приводит к ошибке типа. Это неожиданно.
export class ConcreteFoo extends Foo {
bar(param: string): string {
return param
}
}
Это позволяет мне делать:
const inst = new ConcreteFoo() as Foo
const res = inst.bar(null)
console.log(res) // res is null, but typescript says it is string
Почему это возможно?
Включены строгие проверки null. Версия Typescript — 4.5.3.
Ответ №1:
Типы параметров метода проверяются двумерно, поэтому, пока типы параметров реализации и абстрактной подписи связаны в любом направлении, он будет проверять тип (в данном случае string
это подтип string | null
)
Вы могли бы использовать синтаксис подписи функции, чтобы избежать этого, но только для интерфейсов (производные классы не могут реализовывать члены функции как методы, к сожалению, ex):
export interface Foo {
bar: (param: string | null) => string
}
export class ConcreteFoo implements Foo{
bar(param: string /* | null */): string { // error
return param!
}
}
В настоящее время нет флага для изменения этого поведения (начиная с TS 4.6). Вы можете немного прочитать о причинах этого решения в PR, который представил strictFunctionTypes
Если вы хотите узнать больше о том, что такое дисперсия и как она работает в typescript, вы можете ознакомиться с моим докладом на эту тему