#typescript #typescript-generics
#typescript #typescript-generics
Вопрос:
Мне любопытно, как правильно вводить параметры функции, касающиеся обобщений.
Глядя на следующий базовый пример, у меня есть 2 функции: — sayHello
amp; runAnyFunction
Итак, первый вызов sayHello
явно является ошибкой, данные, переданные функции, не имеют name
параметра. Идеально и ожидаемо.
Проблема в следующей части, где у нас есть функция, runAnyFunction
которая принимает функцию в качестве своего первого параметра, obj
в качестве своего второго параметра и просто запускает функцию, передаваемую obj
в качестве аргумента.
Следующие 2 функции в приведенном ниже примере без проблем пройдут проверки typescript, и это моя проблема.
runAnyFunction<Person>(sayHello, {
name: "Bob"
});
runAnyFunction<Monster>(sayHello, {
size: "HUGE"
});
Я знаю, что второй вызов выдаст мне Hello undefined
, что нежелательно. В идеале я бы хотел, чтобы этот вызов не выполнял проверку типа, поскольку это не должно быть разрешено.
Я думаю, что виновником здесь является fn
параметр функции, поскольку его собственный obj
параметр будет выведен как any
, но у меня возникают трудности с написанием правильного набора текста для этого.
Я понимаю, что в этой демонстрации my runAnyFunction
— это функция, которая на самом деле просто запускает любую функцию, но если есть предпочтительный способ ввести функцию такого рода, я хотел бы знать.
Как я могу правильно ввести это?
Пример кода
// demo.ts
type Fn = (obj) => string;
interface Person {
name: string;
}
interface Monster {
size: string;
}
const somePerson: Person = {
name: "Bob"
};
const someMonster: Monster = {
size: "HUGE"
};
sayHello(someMonster); // ERROR, 'name' is missing in type. Sure, expected.
// sayHello requires an obj of type Person
export function sayHello(obj: Person): string {
return `Hello ${obj.name}`;
}
// Simple function that runs any function, passing obj to it
export function runAnyFunction<T>(fn: Fn, obj: T): void {
const res = fn(obj);
console.log(res);
}
// Person has name, this works
runAnyFunction<Person>(sayHello, {
name: "Bob"
});
// I'm passing sayHello, which should require an object with a `name`
// but it does not error
runAnyFunction<Monster>(sayHello, {
size: "HUGE"
});
Ответ №1:
Вам также нужно сделать свой Fn
тип универсальным:
type Fn<T> = (obj: T) => string;
export function runAnyFunction<T>(fn: Fn<T>, obj: T): void {
const res = fn(obj);
console.log(res);
}
Причина, по которой вы не получали ошибку раньше, заключается в том, что ваш Fn
тип implicity имел any
тип для своего первого параметра:
type Fn = (obj) => string; // obj is implicitly of type any
Комментарии:
1. идеально, имеет полный смысл. Спасибо!
2. Всегда пожалуйста. Я рад, что вы смогли понять такое короткое объяснение.