下面我相信我遇到了循环类型的问题,这是因为MethodReturns
是为user
的this.every
和userId
的this.every
运行的。
错误如下:
'user'隐式具有类型"any",因为它没有类型注释,并且在其自身的初始值设定项中直接或间接引用。(7022(
以下是链接:
PlaygroundLink
这是代码:
export type ThenArg<T> = T extends Promise<infer U> ? U : T
export type FirstArg<T extends any> =
T extends [infer R, ...any[]] ? R :
T extends [] ? undefined :
T;
export type MethodReturns<C extends any, M extends Array<keyof C>> = {
[K in M[number]]: C[K]['fn'] extends ((...args: any[]) => any) ? FirstArg<ThenArg<ReturnType<C[K]['fn']>>> : never
}
type User = { id: number, uuid: string, name: string }
const getUserById = (id: number): User => ({ id, uuid: '1234', name: 'thomas' })
const getUserByUuid = (uuid: string): User => ({ id: 1, uuid, name: 'thomas' })
class Example {
every <T extends Array<keyof Example>, M extends MethodReturns<Example, T>, G>(a: T, b: (solo: M) => G) {
// return function (): G {
// return b({} as M) as G
// }
return { keys: a, fn: b}
}
steve = this.every(['woof'], ({ woof }) => woof + 1)
meow = this.every([], () => 1)
woof = this.every(['meow'], ({ meow }) => meow + 1)
user = this.every(['userId'], ({ userId }) => getUserById(userId))
userId = this.every(['user'], ({ user }) number => user.id)
}
有没有一种方法可以在语法上完成这项工作,而不会引起问题。正如你在上面看到的,我正在输入这些返回值,但它仍然没有起到作用:
理想情况下,我可以为this.every
提供一个可选类型,允许MethodReturns
在可用的情况下以某种方式使用它。
class Example {
user = this.every<number>(['userId'], ({ userId }) => getUserById(userId))
userId = this.every<User>(['user'], ({ user }) number => user.id)
}
我也会接受任何其他语法作为答案。
我认为您将不得不手动注释您的属性。这可能可以通过适当类型的类型别名来简化,比如这样做:
type PropThing<T, K extends keyof Example> =
{ keys: K[], fn: (solo: MethodReturns<Example, K[]>) => T }
然后以下应该可以防止错误:
user: PropThing<User, "userId"> = this.every(['userId'], ({ userId }) => getUserById(userId))
userId: PropThing<number, "user"> = this.every(['user'], ({ user }) => user.id)
好吧,希望能有所帮助;祝你好运
链接到代码