#typescript #type-inference
#typescript #вывод типа
Вопрос:
В следующем фрагменте почему typescript не выводит фактический F
тип в качестве возвращаемого типа функций, а выводит его только как bound ( GenericPerson
), у которого нет свойства ‘address’ ?
type GenericPerson = { name: string; };
type GenericCompany<X extends GenericPerson> = { companyName: string; employees: X[]; };
const getEmployeeDetails= <F extends GenericPerson, T extends GenericCompany<F>>(company: T): F[] => {
return company.employees;
};
getEmployeeDetails({
companyName: 'XYZ',
employees: [
{
name: 'John',
address: 'London',
}
],
}).map((x) => {
console.log(x.address); // Property 'address' does not exist on type GenericPerson
});
[Игровая площадка]
Я могу это исправить, явно указав аргументы типа
type ExtendedPerson = {name: string; address: string};
getEmployeeDetails<ExtendedPerson, GenericCompany<ExtendedPerson>>({
companyName: 'XYZ',
employees: [
{
name: 'John',
address: 'London',
}
],
}).map((x) => {
console.log(x.address); // Type-checks.
});
[Игровая площадка]
Или с помощью условного с infer
(где я должен вставить приведение)
type InferMe<T extends GenericCompany<any>> = T extends GenericCompany<infer R> ? R : never;
function getEmployeeDetails<F extends GenericPerson, T extends GenericCompany<F>>(company: T): InferMe<T>[] {
return company.employees as InferMe<T>[];
}
[Игровая площадка]
Вопрос: Есть ли причина для этого? / Есть ли способ обойти это без приведения и без принуждения вызывающего абонента явно указывать аргументы?
Ответ №1:
Это должно выполнить работу:
function getEmployeeDetails<F extends GenericPerson>(company: GenericCompany<F>): F[] {
return company.employees;
}
getEmployeeDetails({ companyName: 'XYZ', employees: [{ name: 'John', address: 'London' }], })
.map(x => console.log(x.address)); // property 'address' recognized correctly.
Ответ №2:
Вам не нужна F
переменная универсального типа, ее можно упростить:
const getEmployeeDetails = <T extends GenericCompany<GenericPerson>>(company: T): T['employees'] => {
return company.employees;
};