В Typescript у меня есть общий c интерфейс, представляющий тип, который я хочу передать функции.
//foo must be an object {}, not a number or string or boolean or array
interface MyInterface<T extends {[key: string]: any}> {
foo: T
}
Поэтому я делаю свою функцию generi c, но TS не выводит ограничение из моего интерфейса
const myGenericFn: <T, U extends MyInterface<T>>(bar: U) => void = (bar) => {
//Why is T not constrained to {[key: string]: any}?
//Shouldn't the constraint be inferred from MyInterface<T>?
// Or be an error since T doesn't extend {[key: string]: any}?
//bar.foo is T but T does not extend {[key: string]: any}!
const baz = bar.foo
}
//No error! Should be constrained to {foo: {[key: string]: any}} but accepts {foo: string}!
myGenericFn({foo: "bar"})
Единственный способ, который я вижу для выполнения этой работы, - это повторить ограничение на T вот так
const myGenericFnNotDRY: <T extends {[key: string]: any}, U extends MyInterface<T>>(bar: U) => void = (bar) => {
//Not DRY, I have to repeat my generic constraint everywhere I want to use MyInterface within a generic fn!
//bar.foo now correctly extends {[key: string]: any}
const baz = bar.foo
}
//Errors as expected, string not assignable to {[key: string]: any}
myGenericFnNotDRY({foo: "bar"})
Это похоже на довольно большую дыру в TS - - он молча отбрасывает ограничение типа, не сообщая мне. Это может легко привести к очень сложным для отслеживания ошибкам. Скорее всего, мне не хватает какой-то фундаментальной концепции.
TS Playground для вышеуказанного кода
Почему TS не выводит ограничение на T из MyInterface? Как мне ввести мою функцию, чтобы T был правильно ограничен ограничением, указанным c на MyInterface?