Rea*_*lar 6 generics typescript
我有以下接口定义了一个对象,其中属性可以是两种不同的类型。
export interface OptionsA {
name: string;
}
export interface OptionsB {
parts: number;
}
export interface OptionsConfig {
[key: string]: OptionsA | OptionsB;
}
Run Code Online (Sandbox Code Playgroud)
这工作正常,但有一个限制,即类型的属性OptionsB必须以"@".
例如;
const example: OptionsConfig = {
'@sample': {parts: 1},
other: {name: 'example'}
};
Run Code Online (Sandbox Code Playgroud)
所以上面的工作正常,但下面的例子是不正确的。
const example: OptionsConfig = {
'@sample': {parts: 1},
other: {name: 'example'},
'@wrong': {name: 'error'}
};
Run Code Online (Sandbox Code Playgroud)
我想知道是否可以用 TypeScript 声明@wrong只能实现OptionsB接口,因为它有@前缀。
或者,是否有另一种方法来实现类似的限制。
Azi*_*ved 34
Typescript 4.1 为我们提供了按键重新映射,因此您可以执行以下操作:
type addPrefixToObject<T, P extends string> = {
[K in keyof T as K extends string ? `${P}${K}` : never]: T[K]
}
Run Code Online (Sandbox Code Playgroud)
那么,你的OptionsConfig就变成了
export interface OptionsConfig {
[key: string]: OptionsA | addPrefixToObject<OptionsB, '@'>;
}
Run Code Online (Sandbox Code Playgroud)
Typescript Playground中提供了示例。
Nik*_*las 13
TL;DR:复制第一个代码块
虽然在提出这个问题时这可能是不可能的,但我在寻找可以简单复制和粘贴的解决方案时遇到了这个问题。TypeScript 4.1 为我们提供了模板文字,使这种实现成为可能。
TypeScript Playground 的完整示例位于此处。
首先,我们需要定义一些实用程序类型来自动为对象类型添加前缀。这可以通过以下代码块来完成。如果您还不熟悉它们,我建议您首先阅读模板文字和条件类型,它们在下面的代码中大量使用
type addPrefix<TKey, TPrefix extends string> = TKey extends string
? `${TPrefix}${TKey}`
: never;
type removePrefix<TPrefixedKey, TPrefix extends string> = TPrefixedKey extends addPrefix<infer TKey, TPrefix>
? TKey
: '';
type prefixedValue<TObject extends object, TPrefixedKey extends string, TPrefix extends string> = TObject extends {[K in removePrefix<TPrefixedKey, TPrefix>]: infer TValue}
? TValue
: never;
type addPrefixToObject<TObject extends object, TPrefix extends string> = {
[K in addPrefix<keyof TObject, TPrefix>]: prefixedValue<TObject, K, TPrefix>
}
Run Code Online (Sandbox Code Playgroud)
addPrefix如果扩展类型字符串,则接受现有的并向其TKey添加 a 。如果它不扩展类型,则作为类型返回。TPrefixTKeystringneverremovePrefix接受 aTPrefixedKey和 aTPrefix并通过使用检索用于创建 的原始密钥TPrefix来从密钥中删除。inferTPrefixedKeyprefixedValue接受TObject没有前缀的a 。然后它TValue从TPrefixedKey使用 删除前缀后的进行推断removePrefix。如果成功TValue则返回。否则,返回一个空字符串,它仍然是一个有效的对象签名。addPrefixToObject将以上所有内容放在一起。它映射当前内部的所有键TObject并为其添加前缀。该值是通过使用 检索的prefixedValue。如果你将其付诸实践,效果似乎相当不错:
const myConfig: OptionsConfig = {};
// Works:
myConfig.attr1 = {name: 'name'};
myConfig.attr2 = {"@parts": 1};
myConfig.attr3 = {"@parts": 1, name: 'name'};
// Error: Type '{ parts: number; }' is not assignable to type 'OptionsA | addPrefixToObject<OptionsB, "@">'.
myConfig.attr4 = {"parts": 1};
// Prints as:
// type prefixedOptionB = {
// "@parts": number;
// }
type PrefixedOptionB = addPrefixToObject<OptionsB, '@'>;
Run Code Online (Sandbox Code Playgroud)
所有这些可能都可以进一步优化,所以如果您有任何建议,请发表评论。
TypeScript Playground 的完整示例位于此处。
小智 5
使用类型强制执行前缀的一个快速答案(从 TS4.1 开始)-
type strWithPre = `pre-${string}`
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2727 次 |
| 最近记录: |