【问题标题】:How to limit properties in typescript objects to strictly defined properties如何将打字稿对象中的属性限制为严格定义的属性
【发布时间】:2018-07-27 10:09:58
【问题描述】:

给定以下代码:

interface t1 {
  prop1: string;
}

interface t2 {
  prop2: string;
}

type ts = t1 | t2;

const t: ts = {
  prop1: 'foo',
  prop2: 'bar'
}

t 对象为什么有效?这是否可以禁止,所以t 只能t1t2,但不能同时是两者?

代码可以在打字稿游乐场here看到。

【问题讨论】:

    标签: typescript


    【解决方案1】:

    如果接口是兼容的(即它们没有任何不兼容类型的属性),Typescript 将允许您在联合类型中指定任何属性。我们可以定义一个类型,确保对象字面量只与其中一个接口兼容,方法是向联合类型的每个类型添加来自其他类型的所有属性,并使用 never 类型:

    type Diff<T extends string, U extends string> = ({[P in T]: P } & {[P in U]: never } & { [x: string]: never })[T];  
    type Exclude<T, TExclude> = Partial<Record<Diff<keyof TExclude, keyof T>, never>>
    type ts = (t1 & Exclude<t1,t2>) | (t2 & Exclude<t2, t1>);
    
    interface t1 {
        prop1: string;
        prop4: string;
        propCommon: string;
    }
    
    interface t2 {
        prop2: string;
        propCommon: string;
    }
    const t: ts = { prop1: 'foo',prop2: 'bar', propCommon: ''}
    const tt2: ts = {prop2: '', propCommon: ''}
    const tt1: ts = {prop1: '', propCommon: '', prop4: ''}
    

    对于 3 种类型,用法是:

    type ts = (t1 & Exclude<t1,t2> & Exclude<t1, t3>) 
        | (t2 & Exclude<t2, t1> & Exclude<t1, t3>)
        | (t3 & Exclude<t3, t1> & Exclude<t3, t2>);
    

    我们还可以定义一些辅助类型来让这个看起来更好一点:

    type Exclusive2<T, TExclude> = T & Exclude<T,TExclude>
    type Exclusive3<T, TExclude, TExclude2> = T & Exclude<T,TExclude> & Exclude<T,TExclude2>
    type Exclusive4<T, TExclude, TExclude2, TExclude3> = T & Exclude<T,TExclude> & Exclude<T,TExclude2> & Exclude<T, TExclude3>
    type ts = Exclusive3<t1, t2, t3> | Exclusive3<t2, t1, t3> | Exclusive3<t3, t2, t1>
    

    【讨论】:

    • 我认为您的意思是“联合”而不是“交叉点”?
    • 除了生成的非常困难的错误消息之外,这是一个不错的解决方案。谢谢!
    • @RasmusHansen 不幸的是你不能拥有这一切
    • 确实如此,但这符合我让编译器帮助处理一些极其困难的调用的目的。
    • @jcalz 是的!谢谢,我总是把它们弄混:)
    猜你喜欢
    • 1970-01-01
    • 2017-01-04
    • 2021-12-16
    • 2018-08-21
    • 1970-01-01
    • 1970-01-01
    • 2018-12-31
    • 1970-01-01
    • 2014-06-11
    相关资源
    最近更新 更多