我正在学习TypeScript,并决定尝试在我的代码库的一小部分实现它,以使球滚动。具体来说,我现在正在重构的是一个用于为Jest测试生成夹具的夹具“工厂”。
除了这些工厂,这些工厂吐出了某些对象,我还拥有一些助手方法,使生成多个对象的工作变得更容易一些。
一个工厂相当简单,它看起来像这样(值是用faker.js伪造的):
function channelFactory(): ChannelItem {
return { foo: "bar" }
}
ChannelItem只是一个简单的对象,包含一些键。
interface ChannelItem { foo: string; }
作为其中一个帮助方法的例子,我有一个createMany
函数,它接受一个工厂函数和一个Count作为参数
function createMany(factory: () => Record<string, unknown>, count = 1): Record<string, any>[] {
// A for loop that calls the factory, pushes those into an array and returns that array
}
但是,如果我试图在某个地方使用这些工厂,例如在将一些创建的通道持久化到DB的函数中,我会得到TS编译器警告我,Record<string, any>[]
不能分配给ChannelItem[]
。
function saveChannels(payload: ChannelItem[]): void { // Unimportant implementation details }
const items = createMany(channelFactory, 5);
saveChannels(items) // => Argument type Record<string, any>[] is not assignable to parameter type ChannelItem[] Type Record<string, any> is not assignable to type ChannelItem
我知道这是一个常见的接口问题(#15300问题),可能的解决方案是声明一个type
而不是一个interface
,但是在这种情况下,我仍然会收到同样的警告。
type ChannelItem = { foo: string } // Still gives me the above warning
让我的factory
函数更通用的理想方法是什么?
发布于 2022-10-13 14:46:24
您可以使createMany函数成为通用函数:
function createMany<K extends string, T>(factory: () => Record<K, T>, count = 1): Record<K, T>[] {
const arr = [];
for (let i = 0; i < count; i++) {
arr.push(factory());
}
return arr;
}
const items = createMany(channelFactory, 5);
console.log(items);
// Prints:
//[
// { foo: 'bar' },
// { foo: 'bar' },
// { foo: 'bar' },
// { foo: 'bar' },
// { foo: 'bar' }
//]
我之所以创建K extends string
,是因为您指定希望您的记录具有字符串键。你想做什么都行。
只需自己填写这些功能,不确定你想要做些什么。
发布于 2022-10-13 14:57:18
createMany
甚至不需要知道factory
返回的类型。
您可以使它具有更大的灵活性。
interface ChannelItem { foo: string; }
function channelFactory(): ChannelItem {
return { foo: "bar" }
}
function createMany<T>(factory: () => T, count = 1): T[] {
// A for loop that calls the factory, pushes those into an array and returns that array
return []
}
function saveChannels(payload: ChannelItem[]): void { }
const items = createMany(channelFactory, 5);
saveChannels(items)
https://stackoverflow.com/questions/74057601
复制相似问题