是否有可能让 TypeScript 正确地推断出
callback
函数中的 funcAorB
参数的类型?我希望由于 TypeScript 能够确定 data
参数的正确类型,因为 switch
语句测试了 key
成员,它也会在 T
泛型类型所在的任何地方使用相同的类型在函数中使用。
我喜欢在调用
callback
时正确推断出 funcAorB
的类型,我只希望我能在 funcAorB
中得到相同的推断。
type DataA = {
readonly key: 'a',
};
type DataB = {
readonly key: 'b',
};
function funcA(data: DataA, callback: (data: DataA) => void) {}
function funcB(data: DataB, callback: (data: DataB) => void) {}
function funcAorB<T extends DataA | DataB>(data: T, callback: (data: T) => void) {
switch (data.key) {
case 'a': {
// TypeScript believes that data is of type DataA now.
// But, I have to use "as" because TypeScript thinks that
// callback can be ((data: DataA) => void | (data: DataB) => void).
funcA(data, callback as (data: DataA) => void);
break;
}
case 'b': {
// TypeScript believes that data is of type DataB now.
// But, I have to use "as" because TypeScript thinks that
// callback can be ((data: DataA) => void | (data: DataB) => void).
funcB(data, callback as (data: DataB) => void);
break;
}
}
}
// The callback type is inferred properly at the call site.
funcAorB({ key: 'a' }, (data) => {
// This succeeds because data is inferred to be DataA.
const a: 'a' = data.key;
});
// The callback type is inferred properly at the call site.
funcAorB({ key: 'b' }, (data) => {
// This succeeds because data is inferred to be DataB.
const b: 'b' = data.key;
});
是的,可以让 TypeScript 正确推断 funcA 或 funcB 函数中回调参数的类型。您可以通过使用函数重载来根据数据参数的类型定义两种可能的回调参数类型来实现这一点。
function funcAorB(data: DataA, callback: (data: DataA) => void): void;
function funcAorB(data: DataB, callback: (data: DataB) => void): void;
function funcAorB<T extends DataA | DataB>(data: T, callback: (data: T) => void): void {
switch (data.key) {
case 'a': {
funcA(data as DataA, callback as (data: DataA) => void);
break;
}
case 'b': {
funcB(data as DataB, callback as (data: DataB) => void);
break;
}
}
}
通过这些函数重载,TypeScript 将根据数据参数的类型正确推断回调参数的类型。现在您可以使用正确类型的回调参数调用 funcAorB,TypeScript 将不需要您使用 as 断言运算符:
funcAorB({ key: 'a' }, (data) => {
// TypeScript infers that data is of type DataA here.
const a: 'a' = data.key;
});
funcAorB({ key: 'b' }, (data) => {
// TypeScript infers that data is of type DataB here.
const b: 'b' = data.key;
});