gpt4 book ai didi

typescript - 使用 TypeScript 中的类型定义对象键的前缀

转载 作者:行者123 更新时间:2023-12-04 11:54:28 27 4
gpt4 key购买 nike

我有以下接口(interface)定义了一个对象,其中属性可以是两种不同的类型。

export interface OptionsA {
name: string;
}

export interface OptionsB {
parts: number;
}

export interface OptionsConfig {
[key: string]: OptionsA | OptionsB;
}

这工作正常,但有一个限制,即 OptionsB 类型的属性必须以 "@" 为前缀.

例如;

const example: OptionsConfig = {
'@sample': {parts: 1},
other: {name: 'example'}
};

所以上面的工作正常,但下面的例子是不正确的。

const example: OptionsConfig = {
'@sample': {parts: 1},
other: {name: 'example'},
'@wrong': {name: 'error'}
};

我想知道 TypeScript 是否可以声明 @wrong只能实现 OptionsB接口(interface),因为它有 @字首。

或者,是否有另一种方法来实现类似的限制。

最佳答案

TL;DR:复制第一个代码块🚀
虽然在问这个问题时这可能是不可能的,但我在寻找可以简单复制和粘贴的解决方案时遇到了这个问题。 TypeScript 4.1 gave us template literals这使得这种实现成为可能。
TypeScript 操场上的完整示例是 here .

首先,我们需要定义一些实用程序类型来自动为对象类型添加前缀。这可以通过以下代码块完成。如果您还不熟悉它们,我建议您先阅读 template literalconditional在下面的代码中大量使用的类型⬇️

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>
}
  • addPrefix接受现有的 TKey并添加一个 TPrefix到它,如果TKey扩展类型字符串。如果不扩展类型string , never而是作为类型返回。
  • removePrefix接收 TPrefixedKey和一个 TPrefix并删除 TPrefix从 key 使用 infer检索用于创建 TPrefixedKey 的原始 key .
  • prefixedValue接收 TObject这是 不是 前缀。然后它推断 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, '@'>;
    并且自动完成也相应地工作:
    screenshot of autocompletion

    所有这些都可以进一步优化,所以如果您有任何建议,请发表评论。祝你有个美好的一天👋
    TypeScript 操场上的完整示例是 here .

    关于typescript - 使用 TypeScript 中的类型定义对象键的前缀,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57510388/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com