【问题标题】:Type describing alternative keys描述替代键的类型
【发布时间】:2017-11-22 20:42:00
【问题描述】:

我有一个看起来像这样的对象:

const object = { a: 10, an: 20 };

对象不是我定义的,而是我从其他地方收到的对象。该对象的键可以取自:

const keys = {
    /**
     * A long name that describes what "a" stands for.
     */
    aReallyLongName: "a",

    /**
     * Another long name that describes what "an" stands for.
     */
    anotherReallyLongName: "an"
};

为了从object 中获取10 的值,我这样写:

object[keys.aReallyLongName] // 10

有什么方法可以以类型安全的方式使用aReallyLongName 来引用objecta 属性?


请注意,我想要一种使用长名称来引用短名称的方法,而不是相反。基本上,我想要一种以类型安全的方式(即使作为别名,它也不必在keys 对象)。

我想要一种将object.aReallyLongName 之类的东西编译为object.a 的方法,并且让编译器知道该值应该是number

可能是这样的:

interface Data {
    /**
     * A long name that describes what "a" stands for.
     */
    "a" as "aReallyLongName": number;

    /**
     * Another long name that describes what "an" stands for.
     */
    "an" as "anotherReallyLongName": number;
}

object.aReallyLongName // compile to: object.a

用例

1。映射从 API 或库接收的数据

API 可能会返回缩写键、在项目上下文中看起来不正确的键或需要更多描述的键。例如,一个 API 可能会返回

{ "prop": { "cat": "Test", "long_description": "Lorem" } }

如果能够定义一个描述这个数据结构的接口就好了,但同时用properties代替propcategory代替catdescription代替@ 987654344@.

2。 MongoDB 文档键的缩写

要优化 MongoDB 中的存储,一种方法是缩写文档的键。文档可能如下所示:

{ "p": { "n": "John Doe", "a": "Example Street" } }

同样,如果能够描述此文档的键和值类型,那将是很好的,但同时使用person 而不是pname 而不是naddress 而不是a,无需创建 ORM 层。

【问题讨论】:

    标签: typescript types


    【解决方案1】:

    您可以使用 keyof 运算符来完成。

    它看起来像这样(我将键设置为可索引的对象,因此它的属性可以有任何名称,但如果需要,您可以指定它们):

    const object = { a: 10, an: 20 };
    
    type Keys = keyof typeof object;
    
    const keys: { [index: string]: Keys } = {
        aReallyLongName: "a",
        anotherReallyLongName: "an"
    };
    

    如果输入不是 object 的键的值,则会出现编译错误:

    const object = { a: 10, an: 20 };
    
    type Keys = keyof typeof object;
    
    const keys: { [index: string]: Keys } = {
        aReallyLongName: "B",
        anotherReallyLongName: "xn"
    };
    

    您可以在手册here 的“高级类型”部分阅读更多相关信息。

    或者,您可以只使用一个装饰器类,该类定义与原始对象不同名称的 getter 和 setter。

    它看起来像这样。

    const object: { a: number, an: number } = { a: 10, an: 20 };
    
    class ObjectDescriptor {
        constructor(private original: typeof object) {
    
        }
    
        public get AReallyLongName() {
            return this.original.a;
        }
    
        public set AReallyLongName(value) {
            this.original.a = value;
        }
    
    }
    

    您将能够像这样访问它。

    let descriptor = new ObjectDescriptor(object);
    descriptor.AReallyLongName;
    

    【讨论】:

    • 这将使keys 类型安全,但不会使object 类型安全。我仍然可以写object["c"] 并且无法知道我可以使用keys 中的哪些键(不是哪些值)。我想要的是一种以类型安全的方式使用aReallyLongName 来引用object 上的属性的方式,而不是相反。
    • 我不认为打字稿只允许你在你做 object.c 时输入那个访问器,它会抱怨。可能是因为它是运行时值。
    • 而键入的方法是将键对象的值限制为原始对象的键。这就是我的建议。
    • 我的回答是这样的,所以键对象的值只能是对象对象的键。但这不会阻止你调用 object['an'] 。
    • 谢谢,我明白了,但很遗憾这不是我要找的。​​span>
    猜你喜欢
    • 2011-07-24
    • 2021-06-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-09
    • 2014-02-11
    • 2018-08-23
    • 1970-01-01
    相关资源
    最近更新 更多