如何使用TypeScript验证对象与接口没有重叠的属性?

时间:2019-10-18 15:55:59

标签: javascript typescript types

我有一个接口function() { var n = e("./styles/css/styles.scss") , t = document.createElement("style"); t.innerHTML = n, document.head.appendChild(t) }(), 和一个对象[Report Only] Refused to apply inline style because it violates the following Content Security Policy directive: "style-src 'self' 'nonce-b123d558a63bc7e84aa7' ". Either the 'unsafe-inline' keyword, a hash ('sha256-SamqqFx+xVKq8AnoIWgeammNlDl/h4AP94HthfQO43Q='), or a nonce ('nonce-...') is required to enable inline execution. ,其类型未知。如果V的任何属性是x的键,我想抛出运行时错误。 TypeScript最友好的方式是什么?

这是一个明显的例子:

x

尽管我希望使用类型系统来使此检查隐式化,但我知道有上百万种使用JavaScript的方法(例如,保留无效字符串数组等)。


编辑:我对使用无效键数组的担心是,如果我更改接口,我不想忘记更新数组。如果我使用数组,则需要一种类型检查的方法来确保它与接口保持一致。

3 个答案:

答案 0 :(得分:2)

一旦您接受了一个不幸的事实,您就需要维护一些与V相关的运行时工件,因为V本身就是erased,并假设您实际上无法使用要定义 V的运行时工件,如果您的运行时工件和V不同步,那么最好的办法就是让编译器大吼大叫。这是一种实现方法:

interface V {
    a: number;
    b: string;
}

const keysOfV = ["a", "b"] as const;
type MutuallyAssignable<T extends U, U extends V, V = T> = void;
// the following line will give an error if keysOfV is wrong
type KeysOfVIsGood = MutuallyAssignable<keyof V, typeof keysOfV[number]>; // okay

请注意as const的定义中的keysOfV。那是const assertion,需要它(或类似的东西)来使编译器跟踪keysOfV的文字字符串元素,而不是推断出正确但太宽的类型{{1} }。

然后,string[]是一种求值为MutuallyAssignable<T, U>的类型,但我们实际上并不关心它求值的含义。我们关心的是voidconstrainedT,而U被约束到U(通过default参数避开了违反循环约束)。在某些类型TMutuallyAssignable<X, Y>上使用X时,如果编译器不认识到YX是可相互分配的,则会出现编译器错误。 。

然后,您可以根据需要使用Y继续定义和使用hasInvalidProperties()函数。也许像这样:

keysOfV

主要事件是function hasInvalidProperties(x: object): x is { [K in keyof V]: Record<K, any> }[keyof V] { return Object.keys(x).some(k => hasInvalidProperties.badKeySet.has(k)); } hasInvalidProperties.badKeySet = new Set(keysOfV) as Set<string>; /// test function getDataFromRequest(): object { return Math.random() < 0.5 ? { c: "okay" } : { a: "bad" }; } const x = getDataFromRequest(); if (hasInvalidProperties(x)) { console.log("not okay"); throw new Error(); } console.log("okay"); 错误时发生的情况。缺少条目时会发生以下情况:

keysOfV

当它有一个额外的条目时,会发生以下情况:

const keysOfV = ["a"] as const;
type MutuallyAssignable<T extends U, U extends V, V = T> = void;
// the following line will give an error if keysOfV is wrong
type KeysOfVIsGood = MutuallyAssignable<keyof V, typeof keysOfV[number]>; // error!
// "b" is not assignable to "a" ------> ~~~~~~~

希望这些错误消息和位置具有足够的描述性,以使您了解在const keysOfV = ["a", "b", "c"] as const; type MutuallyAssignable<T extends U, U extends V, V = T> = void; // the following line will give an error if keysOfV is wrong type KeysOfVIsGood = MutuallyAssignable<keyof V, typeof keysOfV[number]>; // error! // "c" is not assignable to "a" | "b" ---------> ~~~~~~~~~~~~~~~~~~~~~~ 更改时如何解决。


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

Link to code

答案 1 :(得分:1)

如果您愿意使用transformers,则可以在编译时获取接口上的属性列表,然后解析为字符串的运行时列表。因为它依赖于一个用Typescript编写的编译器插件,所以它不是本机TypeScript解决方案,但是它使您不必将接口中的数据复制到字符串列表中。

See details on this answer.

答案 2 :(得分:0)

无法使用Typescript进行此操作,因为在您的代码运行时,您对类型的了解不再。唯一的方法就是使用其他工具。

我们使用的一个系统是json-schema。我们为进出API的所有内容编写模式,并使用工具自动将JSON-Schema转换为Typescript类型。我们不做相反的事情,因为json模式比打字稿更具表现力。

通过这种方式,我们可以使用1个规范的源代码获得运行时验证和静态类型。