typescript - 包含用作接口键的 keyof 的模板文字
问题描述
给定一个简单的界面:
interface Schedule {
interval: "month" | "day";
price: number;
}
我可以构造一个模板文字类型(使用ts4.4
):
type PrefixedScheduleKey = `schedule__${keyof Schedule}`; // "schedule__interval" | "schedule__price"
假设有一些这样的接口,我想合并(基本上展平)它们的前缀、模板文字键,最终得到:
interface Metadata {
foo: string;
bar: string;
// computed
schedule__interval: "month" | "day";
schedule__price: number;
...
}
我应该如何声明这样的接口键?
interface Metadata {
[key: PrefixedScheduleKey]: any
}
// throws
// An index signature parameter type cannot be a literal type or generic type. Consider using a mapped object type instead.(1337)
和
interface Metadata {
[key in `schedule__${keyof Schedule}`]: any
}
// leads to
// A computed property name must be of type 'string', 'number', 'symbol', or 'any'.(2464)
// Member '[key in `schedule__${keyof' implicitly has an 'any' type.(7008)
这里是游乐场。
顺便说一句,在 github上建议使用type
而不是,interface
但这不起作用,因为我的Metadata
接口已经扩展了另一个接口,但我试图保持示例简单。
解决方案
这不可能直接在接口上执行,如此处所述:Typescript: Mapped types with Interface
到目前为止,在 TypeScript 中(从 2.7.2 版开始),接口中的联合类型签名是不允许的,而是应该使用映射类型(正如您正确使用的那样)。
文档。
但是,您可以使用任意接口和映射类型之间的交集类型来实现这一点,如您提到的原始 GitHub 问题(“将其他成员移动到与交集类型组合的单独对象类型”)。您还可以使用as
关键字有效地内联PrefixedScheduleKey
模板文字类型,同时保留key
足够长的时间来引用Schedule[key]
. 没有理由不能对其他带前缀的类型执行相同的操作,无论是在相同的映射元数据类型中还是在您稍后与之相交的相邻元数据类型中。
interface BareMetadata /* extends ArbitraryType */ {
foo: string;
bar: string;
}
type ScheduleMetadata = {
[key in keyof Schedule as `schedule__${key}`]: Schedule[key];
}
type MergedMetadata = BareMetadata & ScheduleMetadata;
const example: MergedMetadata = {
foo: "one",
bar: "two",
schedule__interval: "month",
schedule__price: 9.99
};
令我惊讶的是,您甚至可以使用interface
类似对象的扩展type
,这可能会帮助您避免显式交集:
interface MergedMetadata extends BareMetadata, ScheduleMetadata {}
// or
interface Metadata extends ScheduleMetadata {
foo: string;
bar: string;
}
推荐阅读
- ios - 推送通知单击时xamarin推送通知ios页面导航不起作用
- git - 独立特性的git分支策略
- mysql - 从 MySQL 5.6.35 迁移到 MariaDB 10.6.3 - 查询不起作用
- dockerfile - 如果自定义映像是从 Dockerfile 构建的,则无法启动 Chromium,因为可执行文件不存在
- c - 尝试计算平均值时不是c中的数字输出
- reactjs - 使用 Jest 和 Enzyme 在另一个组件内的 React 按钮上模拟单击
- python - 如何删除 .txt 文件中没有元音的单词?
- c++ - 构造函数问题的未定义引用
- sql - 在数据顶部插入一行,列名称为日期名称
- spring-boot - 用于 Spring Boot 的 Typesafe @Qualifier 以避免字符串错误