【问题标题】:Type for object that has one and only one property from a list of valid property names从有效属性名称列表中键入具有一个且只有一个属性的对象
【发布时间】:2018-12-05 06:08:29
【问题描述】:

我们如何在不创建包含每个可能对象的联合类型的情况下对此进行建模?

type ValidRootPropertyNames =
  'Property1' |
  'Property2';

type ObjectWithRootPropertyNameFromList =
  { Property1: string; } |
  { Property2: string; };

const obj1: ObjectWithRootPropertyNameFromList = { // okay
  Property1: 'foo',
};

const obj2: ObjectWithRootPropertyNameFromList = { // okay
  Property2: 'foo',
};

const obj3: ObjectWithRootPropertyNameFromList = { // error
  Property3: 'foo',
};

上面做了我们需要的;问题是当有几十个有效的属性名称时,它变得很麻烦。

【问题讨论】:

    标签: typescript


    【解决方案1】:

    您可以使用 distributive behavior of conditional types 从键的联合中自动创建联合:

    type ValidRootPropertyNames =
    'Property1' |
    'Property2';
    
    type ObjectWithRootPropertyNameFromList =
        ValidRootPropertyNames extends infer T ? // Introduce a type parameter to have distributive behavior 
        T extends string ? Record<T, string> : never : never;
    
    const obj1: ObjectWithRootPropertyNameFromList = { // okay
        Property1: 'foo',
    };
    
    const obj2: ObjectWithRootPropertyNameFromList = { // okay
        Property2: 'foo',
    };
    
    const obj3: ObjectWithRootPropertyNameFromList = { // error
        Property3: 'foo',
    }; 
    

    【讨论】:

    • @ShaunLuttin 它只是为了引入一个类型参数,条件类型分布在裸类型参数上,所以我们需要引入一个类型参数 ValidRootPropertyNames
    • 在这种情况下,“分发”这个词是什么意思?
    • @ShaunLuttin 这应该解释一下:stackoverflow.com/questions/51651499/…
    • 让我看看我是否理解。 “分发”在这里的意思是“替换”或“替代”。因此,例如,如果我们在联合类型上分配 X,那么我们将用 X 替换每个联合成员。对吗?
    • @ShaunLuttin 有点……分布在联合上意味着条件类型应用于联合的每个成员。所以在这种情况下,Record&lt;T, string&gt; 应用于ValidRootPropertyNames 的每个成员,所以我们得到Record&lt;'Property1', string&gt; | Record&lt;'Property1', string&gt;
    猜你喜欢
    • 2019-10-21
    • 1970-01-01
    • 2020-06-09
    • 2013-06-25
    • 2011-02-25
    • 1970-01-01
    • 2019-03-17
    • 2014-08-26
    • 1970-01-01
    相关资源
    最近更新 更多