#typescript #type-inference #typescript-generics
#typescript #вывод типа #typescript-generics
Вопрос:
Я столкнулся со следующей проблемой (абстрагированной) в проекте, и я действительно смущен, если я делаю что-то не так:
const fooState = {
normal: {
normalProp: "string",
},
normal2: {
normalProp: 0,
},
weird: {
weirdProp: "anything",
},
};
type fooKeys = keyof typeof fooState;
export const getFooState = <T1 extends fooKeys>(arg: T1) => {
const foundState = fooState[arg];
if ("weirdProp" in foundState) {
console.log(foundState.weirdProp); // This line throws an error, even though it is a practical possibility.
}
return foundState;
};
Кода должно быть достаточно, чтобы объяснить мою проблему. Моя цель — обработать конкретный случай по-другому, когда foundState
объект имеет определенное свойство.
В моем примере, если аргумент arg
передается как "weird"
, журнал консоли будет / должен сработать, но TS выдает ошибку. Почему это?
Я ценю все ответы.
Ответ №1:
Похоже, что typescript нуждается в явной защите типа для вашего случая. Динамический способ определения простой одноуровневой функции защиты типа — это
function dynamicCheckTopLevel<V>(a:any,b:V): a is V {
let keys = Object.keys(b)
return keys.every(k => k in a)
}
Вы также могли бы использовать защиту типа специально для этого prop, тогда вы можете четко указать тип, а не выводить из переданного объекта, который имеет примерное значение для ключа
function weirdCheck(x:any): x is {weirdProp:any}{
return x.weirdProp;
}
затем ошибка исчезает
export const getFooState = <T1 extends fooKeys>(arg: T1) => {
const foundState = fooState[arg];
if (dynamicCheckTopLevel(foundState, {weirdProp:5})) { //had to give weirdProp a value, for your purpose it can be anything
console.log(foundState.weirdProp);
}
return foundState;
};
Если вы хотите перейти к более глубокой защите динамического типа, вы можете использовать
function dynamicDeepCheck<V>(a:any,b:V): a is V {
let keys = Object.keys(b) as Array<keyof V>
return keys.every(key => {
if(typeof b[key] === "object"){
return dynamicDeepCheck(a[key], b[key])
}
return (a[key] amp;amp; typeof a[key] === typeof b[key])
})
}
В защите типа верхнего уровня я опустил проверку соответствия значению typeof, поскольку ваше условие защиты неявного типа, похоже, не заботилось о значении prop.