X4V*_*V18 3 generics type-inference typescript
我有一个函数在参数中接受另一个函数。我想返回一个由传入参数的函数的返回类型配置的通用接口。
function doSomething <T>(values: Whatever[], getter: (whatever: Whatever) => T): T[] {
return values.map(value => getter(value));
}
Run Code Online (Sandbox Code Playgroud)
然后我想让 getter 函数成为可选的,并为此使用默认值。问题就在那时发生了。
function doSomething <T>(values: Whatever[], getter: (whatever: Whatever) => T = val => val): T[] {
return values.map(value => getter(value));
}
Run Code Online (Sandbox Code Playgroud)
所以现在我收到错误消息:
错误:(18, 47) TS2322:类型“(val:Whatever)=>Whatever”不可分配给类型“(whatever:Whatever)=>T”。类型“Whatever”不可分配给类型“T”。
你知道我为什么会收到这个错误吗?
先感谢您,
(下面的示例不是我的真实代码,但这更清楚地描述了我的问题)
我正在使用打字稿 2.7.2
问题是默认 getter 函数的返回类型是Whatever,但doSomething声明要求 getter 必须返回T。T是泛型类型参数,它可以是任何东西,不保证Whatever与T. TypeScript 编译器看不到,当提供默认值时,T没有必要,并且返回类型doSomething为Whatever[]。但是您可以使用以下重载声明来表达它doSomething:
function doSomething<T>(values: Whatever[], getter: (whatever: Whatever) => T): T[];
function doSomething(values: Whatever[]): Whatever[];
// the implementation must be compatible with both variants
function doSomething<T>(values: Whatever[], getter: (whatever: Whatever) => T | Whatever = val => val ): (T | Whatever)[] {
return values.map(value => getter(value));
}
Run Code Online (Sandbox Code Playgroud)
更新以解决已澄清的问题:
我想避免返回“Whatever | T”,因为每次调用此函数时,我都必须检查响应类型(Whatever 或 T)。
当您调用此函数时,仅考虑两个重载签名,TypeScript 在 doSomething(). 事实上,实现返回类型可以简单地声明为any,就像在重载文档示例中所做的那样- 它仅用于对实现进行类型检查,并且实现通常足够明显,因此更严格的类型不会提供太多好处。
我想编写代码来获取 getter 函数的返回类型并用作 T。
如果在调用时省略泛型参数doSomething,编译器将T根据getter返回类型进行推断。我认为以下示例可以满足您的要求:
interface Whatever { w: string };
function doSomething<T>(values: Whatever[], getter: (whatever: Whatever) => T): T[];
function doSomething(values: Whatever[]): Whatever[];
function doSomething<T>(values: Whatever[], getter: (whatever: Whatever) => T | Whatever = val => val ): (T | Whatever)[] {
return values.map(value => getter(value));
}
function example() {
const getter1 = (whatever: Whatever) => whatever.w; // returns string
const getter2 = (whatever: Whatever) => whatever.w.length; // returns number
const values: Whatever[] = [];
const r0 = doSomething(values); // const r1: Whatever[]
const r1 = doSomething(values, getter1); // const r1: string[]
const r2 = doSomething(values, getter2); // const r2: number[]
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2755 次 |
| 最近记录: |