#typescript-generics
#typescript-дженерики
Вопрос:
Я сталкиваюсь с этим при использовании перехватов React, но это общий вопрос TypeScript.
Вы можете увидеть это на детской площадке
Когда я использую общий параметр, который я нахожу наиболее интуитивно понятным, функция, которую я передаю, не является полностью типизированной. Пока она возвращает объект с реквизитами в T, компилятор доволен, но я также могу добавить реквизит, который не является частью T. Это становится проблемой, когда у T есть некоторые дополнительные реквизиты, потому что я могу пропустить их по буквам и не знать об этом.
Если я вместо этого задаю явный тип возвращаемого значения для функции, которую я передаю, все работает как ожидалось, но это не интуитивно понятное использование, когда вызываемая функция имеет общий параметр.
Может кто-нибудь, пожалуйста, объяснить, почему компилятор допускает это?
const foo = <T>(f: ()=>T) => {
return f();
};
type Result = {
bar: number;
foo?:number;
}
const strange = foo<Result>(() => {
return {
bar: 42,
baz: 12, // why is this prop allowd?
FOO: 13 // ups I might think I set the foo prop, but I spelled it wrong
};
});
const expected = foo((): Result => {
return {
bar:42,
FOO: 12 // this is not allowd, which is what I wxpected
};
});
Ответ №1:
Проверка избыточного свойства запускается только для «свежего» объектного литерала. Свежесть объектного литерала теряется в случае утверждения типа и расширения типа.
в strange
функции тип возвращаемого типа расширяется (см. Выпуск № 241). Таким образом, избыточные свойства допустимы.
const strange = foo<Result>(() => {
// type widening occurs here
// freshness is lost
// No excess property check triggered
return {
bar: 42,
baz: 12, // excess property allowed
FOO: 13 // excess property allowed
};
});
в expected
функции нет расширения типа, поскольку возвращаемый тип явно указан. свежесть объектного литерала сохраняется, и запускается проверка избыточного свойства
const expected = foo((): Result => {
// No type assertion
// object literal is fresh
// Excess property check is triggered
return {
bar:42,
FOO: 12 // this is not allowd, which is what I wxpected
};
});
Комментарии:
1. Спасибо за ваш ответ. Знаете ли вы, почему это так? В каких ситуациях вы действительно хотите такого поведения?
2. Без расширения возвращаемого типа это приведет к сбою :
const a = () => ({ x: 3, y: 4 }); const b: () => { x: number } = a
.3. Да, и я бы хотел этого, потому что a возвращает что-то, что не является a
{ x: number }
. Если бы я хотел использовать a, как вы предложили, я бы добавил[key: string]: any
к возвращаемому типу b .