我需要使用泛型类型的动态静态字段为函数编写类型
interface WithStatic<P, T extends string[]> {
(props: P): void;
[K in T]: WithStatic<P, T>; // TS Error: A computed property name must be of type 'string', 'number', 'symbol', or 'any'.
}
如果我将动态字段移得更深(将其移至另一个字段),则一切正常:
interface WithStatic<P, T extends string> {
(props: P): void;
options: {
[K in T]: WithStatic<P, T>;
};
}
用法示例:
const withStatic = (props => {}) as WithStatic<{}, 'maybe' | 'ready'>;
然后键入
withStatic.options.
显示maybe
和ready
:
我该如何在接口的根级别定义动态类型?
修改
答案 0 :(得分:3)
除了映射表达式(即[K in T]: ...
)外,映射类型不能包含任何其他声明。而且它也不会出现在界面中。
考虑到这一点,您将需要在类型别名中使用交集来描述所需的类型。这将起作用:
type WithStatic<P, T extends string[]> = {
(props: P): void;
} & {
[K in T[number]]: WithStatic<P, T>;
}
let c = ((p: {}) => 1) as any as WithStatic<{}, ['maybe', 'ready']>
c.maybe.maybe // not sure this is what you are going for here but it compiles..
虽然上面的类型有效,但我不确定它是否真的有意义,也许您希望在T
中声明的字段为特定类型(例如string
或any
或boolean
),则可以只使用映射类型Record
。同样,我们通常将多个键作为联合而不是作为元组传递:
type WithStatic<P, T extends string> = {
(props: P): void;
} & Record<T, string> // replace strign with whatever
let c = ((p: {}) => 1) as any as WithStatic<{}, 'maybe' | 'ready'>
c.maybe = ""
修改
关于评论,您可以允许c.maybe.ready
但不允许c.maybe.maybe
,但是您将需要使用联合而不是元组:
type WithStatic<P, T extends string> = {
(props: P): void;
} & {
[K in T]: Exclude<T, K> extends never? string : WithStatic<P, Exclude<T, K>>; // Added bottom
}
let c = ((p: {}) => 1) as any as WithStatic<{}, 'maybe' | 'ready'>
c.maybe.maybe // error
c.ready.maybe = ""
c.maybe.ready = ""