我正在做TS项目,我有复杂的类结构(抽象工厂)。问题是我的界面看起来像:
export interface IProduct {
customization: Customization;
preparation: Preparation;
make: () => void;
setMilk?: (volume: number) => void;
setWater?: (volume: number) => void;
setSugar?: (volume: number) => void;
}
所以,我有许多类似的setter属性(最后3),它需要更多,但模板是相同的。问题是:有没有办法把它们缩短成一行?看起来像:
['set*': string]: (volume: number) => void;
(可能是索引签名等的一些技巧)
如果您想接受以"set"
开头的任何可能的密钥,包括您没有指定的内容,如"setFlour"
或"setRandomThing"
或"settingSun"
或"set$$1234Blah"
:
在TypeScript 4.4之前,没有办法对特定的对象类型做到这一点。但是,现在支持模板字符串模式索引签名。索引签名的形式为{[dummyKeyName: KeyType]: ValueType}
,其中KeyType
表示您希望签名应用的密钥类型。传统上,KeyType
只能使用string
或number
。TS4.4允许使用形式为`set${string}`
的模式模板文字类型,由microsoft/TypeScript#40598实现,其中string
是一个"pattern"或";placeholder"在模板文字类型中
对于你的例子,这意味着你可以这样写:
export interface IProduct {
customization: Customization;
preparation: Preparation;
make: () => void;
[k: `set${string}`]: (volume: number) => void
}
并进行测试:
declare const p: IProduct;
p.setMilk(1);
p.setSugar(2);
p.setWater(3);
p.setFlour(4); //okay
另一方面,如果您只想接受"milk"
或"water"
或"sugar"
,或其他特定字符串文字类型的枚举联合,则可以通过使用适当的K
和V
类型扩展Record<K, V>
实用程序类型来实现:
namespace ListOfKeys {type SetKeys = 'milk' | 'water' | 'sugar';
export interface IProduct extends Record<
`set${Capitalize<SetKeys>}`, (volume: number) => void
> {
customization: Customization;
preparation: Preparation;
make: () => void;
}
并进行测试:
declare const p: IProduct;
p.setMilk(1);
p.setSugar(2);
p.setWater(3);
p.setFlour(4); //error
Playground链接到代码