从传递函数的返回值推断函数泛型类型U [英] Infer function generic type U from return value of passed function
本文介绍了从传递函数的返回值推断函数泛型类型U的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
简化的示例,有一个用于存储项目的类,其中项目的一些属性是自动生成的(例如,ID是自动生成的数据库):
/**
* Stores items of type T
*/
class Store<T> {
/**
* Return a function that creates items from supplied partial items merged with
* attributes U auto-generated by a generator function
*/
itemCreator<U>(
generate: (item: Omit<T, keyof U>) => U
): (item: Omit<T, keyof U>) => Omit<T, keyof U> & U {
return item => ({...item, ...generate(item)});
}
}
type Person = {
id: string;
name: string;
email: string;
age?: number;
};
因此,如果您创建一个Store<Person>
并提供一个生成器来自动生成id
,则返回的创建者函数只需要name
和email
。
但是,在某些情况下,不会推断U
:
工作:
const create = new Store<Person>()
.itemCreator(() => ({id: 'ID', extra: 42}));
// U is {id: string, extra: number}, `create` only needs to provide `name` and `email` :)
const person = create({name: 'John', email: 'john.doe@foo.com'}); // creates person with extra
不起作用:
const create = new Store<Person>()
.itemCreator(item => ({id: 'ID', extra: 42}));
// U is now unknown, meaning the `create` function must provide complete `Person` objects :(
const person = create({name: 'John', email: 'john.doe@foo.com'}); // does not compile
使用显式<U>
:
const create = new Store<Person>()
.itemCreator<{id: string, extra: number}>((item) => ({id: 'ID', extra: 42}));
const person = create({name: 'John', email: 'john.doe@foo.com'}); // creates person with extra
现在,将部分项传递给生成器的原因是,某些自动生成的属性可能依赖于其他属性(例如,作为email
属性的散列生成的id
):
const creator = new Store<Person>()
.itemCreator(item => ({id: hash(item.email)}))
因此,我的问题是,如果提供了generate
函数的参数,为什么U
推理失败?TypeScrip是否只是使用找到的第一个U
实例,或者原因是什么?generate
函数返回U
,因此如果它看到返回{id: string}
,您可能会认为U
也存在于参数到generate
的Omit
类型中是不相关的?
有没有办法解决这个问题?
推荐答案
@jhh,@linda paiste您认为下一步解决方案是什么?:
class Store<T> {
itemCreator<U>(
generate: <P = Omit<T, keyof U>>(item: P) => U
): (item: Omit<T, keyof U>) => Omit<T, keyof U> & U {
return item => ({ ...item, ...generate(item) });
}
}
type Person = {
id: string;
name: string;
email: string;
age?: number;
};
const create = new Store<Person>()
.itemCreator(item => {
const x = item // Omit<Person, "id" | "extra">
return ({ id: 'ID', extra: 42 })
});
const person = create({ name: 'John', email: 'john.doe@foo.com' });
看起来TS很难推断item
参数,所以我用默认值定义了额外的泛型。
Here,在我的博客中,您可以找到更有趣的回调类型
Here您可以找到Titian CerNicova Dragomir对此行为的解释
如果有参数,检查器需要在检查正文之前确定U,因为没有来源可以推断它与UNKNOWN匹配。然后它检查正文,但不会返回使用
U = ret type
重试,它只检查返回的指南针。U=未知
这篇关于从传递函数的返回值推断函数泛型类型U的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
查看全文