提问人:Gerrol 提问时间:8/4/2022 最后编辑:Gerrol 更新时间:8/4/2022 访问量:706
Typescript - 键入检查对象属性并在 null 时抛出的最佳方法是什么?
Typescript - What is the best way to type check an object properties and throw upon null?
问:
假设我们有这个 Typescript 代码,那么编写 TODO 部分的最佳方法是什么?我和我的团队正在寻找一种优雅的方式来做到这一点
type MyType = {
key1?: string | null
key2?: string | null
key3?: string | null
// ...
// ...
// ...
};
type MyTypeNotNull = {
key1?: string
key2?: string
key3?: string
// ...
// ...
// ...
};
function logMyType(type: MyTypeNotNull) {
console.log(type);
}
const myType: MyType = {
key1: 'myKey1',
// key2 is omitted
key3: null,
// ...
// ...
// ...
};
const run = (value: MyType) => {
/* TODO
- throw when a prop is null
- make myType pass the type check of logMyType
*/
logMyType(value); // Error Type 'string | null | undefined' is not assignable to type 'string | undefined'
};
run(myType);
目前我们有一堆如果互相关注,并且觉得它应该存在一种更好的方法来做到这一点,你有什么干净的建议吗?
答:
您可以编写一个自定义断言函数,该函数遍历其所有参数的属性,如果其中任何一个属性为;返回的断言谓词(形式为 )会将参数的类型缩小到具有所有非 null 属性的版本。下面是一种方法:null
asserts xxx is YYY
function assertNoPropsAreNull<T extends object>(obj: T): asserts obj is
{ [K in keyof T]: Exclude<T[K], null> } {
Object.entries(obj).forEach(([k, v]) => {
if (v === null)
throw new Error("OH NOEZ, PROP \"" + k + "\" IS NULL");
});
}
的实现使用 Object.entries()
方法获取参数的键/值对数组,如果发现值为 null 的任何值(并在错误消息中提及键),则抛出错误。assertNoPropsAreNull()
arg
的调用签名在 中是泛型的,类型为 ,返回类型为 。这是一个映射类型,它只是通过 Exclude<T, U>
实用程序类型从每个属性类型中剥离出来。assertNoPropsAreNull()
T
obj
asserts obj is { [K in keyof T]: Exclude<T[K], null> }
null
让我们来测试一下:
const run = (value: MyType) => {
value; // (parameter) value: MyType
assertNoPropsAreNull(value)
value; /* (parameter) value: {
key1?: string | undefined;
key2?: string | undefined;
key3?: string | undefined;
} */
logMyType(value); // okay
};
编译器行为看起来不错。在调用 之前,类型是 ,之后它被缩小到 。此类型在结构上与您的类型相同,因此接受它而不发出警告。assertNoPropsAreNull(value)
value
MyType
{key1?: string, key2?: string, key3?: string}
MyTypeNotNull
logMyType()
让我们确保运行时行为也是可以接受的:
run({ key1: 'myKey1' }); // {key1: "myKey1"}
run({ key1: 'myKey1', key3: null }); // 💥 OH NOEZ, PROP "key3" IS NULL
这看起来也不错。在第一种情况下,断言成功,因此使用 -compatible 输入调用,而在第二种情况下,断言失败,根本不被调用。logMyType()
MyTypeNotNull
logMyType()
评论