gpt4 book ai didi

typescript - 如何使用 TypeScript 进行类型化元编程?

转载 作者:行者123 更新时间:2023-12-05 01:49:55 26 4
gpt4 key购买 nike

我正在创建一个接收多个键和值的函数,并且应该返回一个具有这些键及其各自值的对象。值类型应与调用函数时传递的值相匹配。

目前,代码可以工作,但输入不准确。

我尝试使用 Factory 方式,希望 typescript 可以为我推断出一些东西。

这是工厂的代码。还有 Playground here.

const maker = (subModules?: Record<string, unknown>) => {
const add = <Name extends string, Q>(key: Name, value: Q) => {
const obj = {[key]: value};
return maker({
...subModules,
...obj
})
}
const build = () => {
return subModules
}

return {
add,
build
}
}

const m2 = maker()
.add('fn', ({a, b}: { a: number, b: number }) => a + b)
.add('foo', 1)
.add('bar', 'aaaa')
.build()
// m2.foo -> 1
// m2.bar -> 'aaaa'
// m2.fn({a: 1, b: 2}) -> 3
m2

还有管道选项(playground)也许这个可能更简单:


type I = <T extends any[]>(...obj: T) => { [P in T[number]['key']]: T[number]['value'] }
const metaMaker: I = <T extends any[]>(...subModules: T) => {
return subModules.reduce((acc, curr) => {
const op = {[curr.key]: curr.value}
return {
...acc,
...op
}
}, {}) as { [P in T[number]['key']]: T[number]['value'] }
}
const m = metaMaker(
{key: 'fn', value: ({a, b}: { a: number, b: number }) => a + b},
{key: 'foo', value: 1},
{key: 'bar', value: 'aaaa'},
)
// m.foo -> 1
// m.bar -> 'aaaa'
// m.fn({a: 1, b: 2}) -> 3
// m

最佳答案

类似于@yeahwhat 的解决方案,但是这个在build 中添加了一些额外的东西.由于您要返回许多记录的交集,因此它很快就会变得困惑。这extends infer O位将交集“折叠”为单一类型。

const maker = <Submodules extends Record<string, unknown> = {}>(subModules?: Submodules) => {
const add = <Name extends string, Q>(key: Name, value: Q) => {
const obj = {[key]: value};
return maker<Submodules & Record<Name, Q>>({
...subModules,
...obj
} as Submodules & Record<Name, Q>)
}

const build = () => {
return subModules as Submodules extends infer O ? { [K in keyof O]: O[K] } : never;
}

return {
add,
build
}
}

我也做了第二个选择:

type Narrow<T> =
| (T extends infer U ? U : never)
| Extract<T, number | string | boolean | bigint | symbol | null | undefined | []>
| ([T] extends [[]] ? [] : { [K in keyof T]: Narrow<T[K]> });

const metaMaker = <T extends { key: string; value: any }[]>(...subModules: Narrow<T>) => {
return (subModules as T).reduce((acc, curr) => {
const op = {[curr.key]: curr.value}
return {
...acc,
...op
}
}, {}) as { [P in T[number]['key']]: Extract<T[number], { key: P }>['value'] }
}

您与原始解决方案非常接近,但我使用了一种特殊类型来缩小给定输入的类型,而无需使用 as const .你丢失的那件是Extract<T[number], { key: P }> 获取该键的特定值。在您为每个键赋予所有值之前。

Playground (contains both)

关于typescript - 如何使用 TypeScript 进行类型化元编程?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73662417/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com