有没有一种方法可以检查Typescript中的类型相等性?

时间:2019-12-15 17:00:48

标签: typescript

如果两种类型不匹配,我想得到一个错误。 我有一个对象:

const ACTIVITY_ATTRIBUTES = {
    onsite: {
        id:  "applied",
        ....
    },
    online: {
        id: "applied_online",
        ....
    },
    ...
} as const

我希望限于服务器可以接受的字符串

export type ContactAttribute = "applied" | "applied_online" | "donated" | "messaged" | "reviewed"

我知道const不能带有类型限制(因为const将被忽略)。但是,有没有一种方法可以检查类型是否相等,以强制id属性为ContactAttribute类型?像这样:

$Values<typeof ACTIVITY_ATTRIBUTES >["id"] === ContactAttribute

5 个答案:

答案 0 :(得分:2)

您应该查看此StackOverflow thread,以了解实现此目的的简便方法。

类似的东西:

const ACTIVITY_ATTRIBUTES = {
    onsite: {
        id:  "applied",
    },
    donation: {
        id: "donated",
    },
    online: {
        id: "applied_online",
    },
    reviewe: {
        id: "reviewed",
    },
}

export type ContactAttribute = "applied" | "applied_online" | "donated" | "messaged" | "reviewed"

function isOfTypeContact (inputId: string): inputId is ContactAttribute {
    return ["applied", "applied_online", "donated", "messaged", "reviewed"].includes(inputId);
}

console.log(isOfTypeContact(ACTIVITY_ATTRIBUTES.onsite.id)) // true

应该工作。

答案 1 :(得分:1)

我想出了一个辅助函数,该函数仅接受其属性具有类型id的{​​{1}}属性的参数,并返回其原始参数,并且不更改其类型:

ContactAttribte

然后您将像这样创建const hasGoodContactAttributes = <T extends Record<keyof T, { id: ContactAttribute }>>(t: T) => t;

ACTIVITY_ATTRIBUTES

如果您犯了一个错误,您将得到一个错误:

const ACTIVITY_ATTRIBUTES = hasGoodContactAttributes({
    onsite: {
        id: "applied",
        otherProp: 123,
    },
    donation: {
        id: "donated",
        alsoOtherProp: 456
        //....
    },
    online: {
        id: "applied_online",
        //....
    },
    reviewe: {
        id: "reviewed",
        //....
    },
}); // as const if you want

好的,希望能有所帮助;祝你好运!

Link to code

答案 2 :(得分:0)

您实际上可以通过使用以下代码来实现:

const ACTIVITY_ATTRIBUTES: {[key: string]: {id: ContactAttribute}} = {
    onsite: {
        id:  "applied",
    },
    donation: {
        id: "donated",
    },
    online: {
        id: "applied_online",
    },
    reviewe: {
        id: "reviewed",
    },
    hi: {
      id: 'applied',
    }
} as const

type ContactAttribute = "applied" | "applied_online" | "donated" | "messaged" | "reviewed"

但是,我怀疑这可能需要更多的类型检查,因为使用上述解决方案,即使id都可以正确检查,您仍然可以为不同的id放置虚假属性。

为避免此问题,您可能要使用discriminated union

例如:

type Contact = {
  id: "applied",
  x: string
} | {
  id: "applied_online"
  y: number
}

利用此功能,可以确保与每个ContactAttribute关联的预期属性将被正确初始化。

答案 3 :(得分:0)

这可以通过使用虚拟验证功能来实现。

const validateType = <T> (obj:T) => undefined 

剩下的就是用类型和对象来调用它:

type ContactAttribute = "applied" | "applied_online" | "donated" | "messaged" | "reviewed"

type ActivityAttributes= {
   [k:string]: {
      id: ContactAttribute 
   }
}

const ACTIVITY_ATTRIBUTES = {
    onsite: {
        id:  "applied",
        ....
    },
    donation: {
        id: "donated",
        ....
    },
    ...
} as const

validateType<ActivityAttributes>(ACTIVITY_ATTRIBUTES) // Will show an error if types don't match. 

答案 4 :(得分:0)

您可以通过结合使用 declare 和死代码来实现这一点。 declare 语句纯粹是编译时,所以我们使用它们来设置我们类型的假“值”。然后我们使用一个死代码块来调用一个接受两个相同类型参数的函数。

type T1 = number;
type T2 = string;

declare const dummy1: T1;
declare const dummy2: T2;
declare function sameType<T>(v1: T, v2: T): void;
if (false) {
    // @ts-ignore: Unreachable code
    sameType(
        // prevent line break so that the ts-ignore is only applied to the above line
        dummy1, dummy2);
}

@ts-ignore 用于消除无法访问的代码错误。

我在 ( 之后添加了一行注释,以防止 prettier 之类的工具将参数放在同一行,这会消除您想要实现的错误。

您也可以使用 as 表达式,它可能更简洁一些。

type T1 = number;
type T2 = string;

declare const dummy1: T1;
if (false) {
    // @ts-ignore: Unreachable code
    dummy1 
        // prevent line break so that the ts-ignore is only applied to the above line
        as T2
}