示例:
// ===== Declaration ===== //
class A {
CONSTS_TYPE: { [key: string]: [any] }
CONSTS: { [key in keyof this['CONSTS_TYPE']]: key }
foo<T extends keyof this['CONSTS_TYPE'] | string>(
type: T,
callback: (...args: T extends keyof this['CONSTS_TYPE'] ? this['CONSTS_TYPE'][T] : any) => any
) { /** some implementation*/ }
}
class B extends A {
CONSTS_TYPE: {
aa: [number],
bb: [string]
}
// Here is the problem
// Type '{ aa: "aa"; bb: "bb"; }' is not assignable to type '{ [key in keyof this["CONSTS_TYPE"]]: key; }'.(2322)
CONSTS: { [key in keyof this['CONSTS_TYPE']]: key } = {
aa: 'aa',
bb: 'bb'
}
}
// ===== Call ===== //
const b = new B;
b.foo(b.CONSTS.aa, (arg) => {
// so that i can know 'arg' is a 'number' type
arg // number type
});
效果很好,但效果不是很好。
我知道'// @ ts-ignore'会很好地工作
但我认为可能还有其他解决方案
答案 0 :(得分:1)
所以,我认为您的代码存在一些问题:
@ts-ignore
。aa: 'aa',
不是一个数字,应该会引发一个错误。并不是您实施它的方式...args: T
中,T
是一个数组,而不是您认为的一个参数...args
中使用foo
?以下是我认为对您有用的解决方法:
// ===== Declaration ===== //
type ValueOf<T> = T[keyof T];
abstract class A {
abstract CONSTS: { [key: string]: any }
foo<T extends ValueOf<this['CONSTS']>>(
type: T,
callback: (arg: T) => any
) { /** some implementation*/ }
}
class B extends A {
CONSTS: {
aa: number,
bb: string
} = {
aa: 5,
bb: 'bb'
}
}
// ===== Call ===== //
const b = new B;
b.foo(b.CONSTS.bb, (arg) => {
// so that i can know 'arg' is a 'string' type
arg // string type
});
答案 1 :(得分:0)
您实际上不是在寻找通用类吗?
declare class Foo<T extends Record<string, [any]>> {
CONST_TYPES: T;
CONSTS: {
[K in keyof T]: K
}
constructor(types: T);
foo<U extends keyof T>(type: U, callback: (value: T[U]) => any): any;
}
const foo = new Foo({ aa: [42], bb: ['foo'] });
foo.foo(foo.CONSTS.bb, (arg) => {
arg // [string]
})
答案 2 :(得分:0)
最后我找到了解决方法
// ===== Declaration ===== //
class A<T extends Record<string, [any?]>> {
foo<U extends keyof T | string>(
type: U,
callback: (...args: U extends keyof T ? T[U] : any) => any
) { /** some implementation*/ }
}
type T_BConstsType = {
aa: [number],
bb: [string]
}
class B extends A<T_BConstsType> {
CONSTS: { [key in keyof T_BConstsType]: key } = {
aa: 'aa',
bb: 'bb'
}
}
// ===== Call ===== //
const b = new B;
b.foo(b.CONSTS.aa, (arg) => {
// so that i can know 'arg' is a 'number' type
arg // number type
});