#typescript
Вопрос:
Итак, у меня есть следующий интерфейс:
interface DoStuffInterface {
doStuff(value: string | number): string | number;
}
Почему при реализации этого интерфейса TS не применяет подпись?
class NumberStuff implements DoStuffInterface {
public doStuff(value: number): string | number { // <====== missing: | string
return value;
}
}
class StringStuff implements DoStuffInterface {
public doStuff(value: string): string | number { // <====== missing: | number
return value.toLowerCase();
}
}
Это легко разбивается с помощью чего-то подобного:
var numberStuff = new NumberStuff();
var stringStuff = new StringStuff();
function run(thing: DoStuffInterface): void {
console.log(thing.doStuff(42));
}
run(numberStuff);
run(stringStuff); // <====== this fails, due to: `42.toLowerCase()`
Итак, почему TS не применяет NumberStuff
amp; StringStuff
, чтобы иметь правильную подпись? Если бы подпись была правильно установлена, это была бы ошибка во время компиляции, вместо этого вы получите ошибку во время выполнения.
Мне не хватает какого-то флага конфигурации? Или это ожидаемое поведение?
Комментарии:
1. Просто не раскрывайте свой вопрос, это ошибки при компиляции:
type doStuff = (value: string | number) => string | number; const doNumberStuff: doStuff = (value: number) => value;
Ответ №1:
TLDR для включения метода изменения желаемого поведения в свойство:
interface DoStuffInterface {
doStuff: (value: string | number) => string | number;
}
Для интерфейсов в соответствии со строгими типами функций положения параметров типа функций проверяются контравариантно (для «опоры функции»), а не двумерно (для метода)
Более строгая проверка применяется ко всем типам функций, за исключением тех, которые возникают в объявлениях методов или конструкторов. Методы исключаются специально для обеспечения того, чтобы общие классы и интерфейсы (такие как
Array<T>
) продолжали в основном ковариантно связываться.