我试图创建一个递归函数类型,它将对象类型中最外层的键作为参数,并返回一个新函数,然后递归地从给定的键中获取对象的下一个最外层的键,直到没有更多的键可用。
如果键不扩展/${string}
,则参数必须是包含键和属性的对象类型:
type Argument<T> = T extends `/${string}` ? T : { [key in T]: string | number }
- 每个. level只有一个不会扩展
/${string}
的密钥。**
- 每个. level只有一个不会扩展
示例
const values = {
'/aaa': {
'/lorem': {
foo: 'hello world',
'/boo': 12345,
},
},
bbb: {
'/ipsum': {
'/dolor': 'lorem ipsum',
amet: 567890,
},
},
'/ccc': ...
};
foo<typeof values>('/aaa')('/lorem')({ foo: '...' }); // should return type of string
foo<typeof values>('/aaa')('/lorem')('/boo'); // should return type of number
foo<typeof values>('/aaa')('/ipsum'); // should fail
foo<typeof values>({ bbb: '...' })('/ipsum')({ amet: '...' }); // should return type of number
foo<typeof values>({ bbb: '...' })('/ipsum')('/dolor'); // should return type of string
foo<typeof values>({ bbb: '...' })('/lorem'); // should fail
我的当前代码
我有一个类型,几乎做的工作。,但不与非/${string}
扩展:(
type Foo<T extends object> = <K extends keyof T>(args: K) => T[K] extends object ? Foo<T[K]> : T[K];
const values = {
'/aaa': {
'/lorem': {
foo: 'hello world',
'/boo': 12345,
},
},
bbb: {
'/ipsum': {
'/dolor': 'lorem ipsum',
amet: 567890,
},
},
};
const foo = {} as Foo<typeof values>
foo('/aaa')('/lorem')('/boo') // works :D
foo('/aaa')('/lorem')({ foo: '...' }) // fails :(
我尝试在函数中处理args类型-但它无法返回下一个键:(
type Foo<T extends object> = <K extends keyof T>(
args: K extends `/${string}` ? K : { [key in K]: string | number }
) => T[K] extends object ? Foo<T[K]> : T[K];
const values = {
'/aaa': {
'/lorem': {
foo: 'hello world',
'/boo': 12345,
},
},
bbb: {
'/ipsum': {
'/dolor': 'lorem ipsum',
amet: 567890,
},
},
};
const foo = {} as Foo<typeof values>
foo('/aaa')('/lorem')('/boo') // works :D
const a = foo({ bbb: '...' })('/ipsum') // fails :(
我甚至不知道我想尝试的是不是可能--但是如果你有任何建议,你会拯救我的一天:)
谢谢你的时间。
1条答案
按热度按时间kmbjn2e31#
嗯,问题似乎出在
{[key in K]: string | number}
上,很明显,typescript不知道T[K]
在那之后是否是一个对象。如果你把它改为{[key: string]: K}
,它就能工作(但{[key: string|number]: K}
不行)。这似乎是Typescript的问题(我使用的是4.7.4版本)。我能做的最好的事情是使用第二个参数而不是对象: