打字稿用户定义的类型保护检查对象具有数组中的所有属性
Typescript user-defined type guard checking object has all properties in array
我正在尝试编写一个 user-defined type guard 来测试给定的值是否具有给定数组中的所有属性。
我正在调用此函数 hasAll
,它在 Javascript 中的实现和用法如下所示:
function hasAll(obj, keysToCheck) {
if (!obj) return false;
for (const key of keysToCheck) {
const value = obj[key];
if (value === null) return false;
if (value === undefined) return false;
}
return true;
}
hasAll({ foo: 'test', bar: 5 }, ['foo', 'bar']); // true
hasAll({ foo: 'test', bar: 5 }, ['foo', 'bar', 'baz']); // false
我现在要做的是将上面的函数变成type guard。这是我目前所拥有的:
// this _almost_ works
type Nullable<T> = T | null | undefined;
type RemoveNullables<T, K extends keyof T> = {
[P in K]-?: T[P] extends Nullable<infer U> ? U : T[P];
};
function hasAll<T, K extends keyof NonNullable<T>>(
obj: T,
keysToCheck: K[],
): obj is RemoveNullables<NonNullable<T>, K> {
// but i'm getting an error here
if (!obj) return false;
const nonNullableObj = obj as NonNullable<T>;
for (const key of keysToCheck) {
const value = nonNullableObj[key];
if (value === null) return false;
if (value === undefined) return false;
}
return true;
}
export default hasAll;
错误信息是:
A type predicate's type must be assignable to its parameter's type.
Type 'RemoveNullables<NonNullable<T>, K>' is not assignable to type 'T'.
我已经阅读 并给出了很好的解释,但是它对我的情况没有帮助。
我想明确声明我的类型T
在运行完这个函数后将符合RemoveNullables<NonNullable<T>, K>
。我真的不在乎 T
是否可以分配给 RemoveNullables<NonNullable<T>, K>
(如果有意义的话)。
- 我做错了吗?有没有更好的方法来编写这种类型保护?
- 如果这种方法没问题,我怎么能告诉打字稿我不在乎类型保护本身是否是 "unsafe"?
这似乎符合您的要求:
type ExcludeNullable<T, K extends keyof NonNullable<T>> = NonNullable<T> & {
[k in K]-?: Exclude<NonNullable<T>[k], null | undefined>
}
function hasAll<T, K extends keyof NonNullable<T>>(
obj: T,
keysToCheck: K[]
): obj is ExcludeNullable<T, K> {
return obj !== null && obj !== undefined
&& keysToCheck.every(k => obj![k] !== null && obj![k] !== undefined);
}
一些注意事项:
T & ...
交集类型保证 ExcludeNullable<T, K>
可分配给 T
。没有这个,映射类型就没有 K
. 中缺少的 T
属性
Exclude
是一种更简单的方法来摆脱 null
和 undefined
比使用带有 infer
. 的条件类型
- 我冒昧地稍微简化了
hasAll
函数的实现。
我正在尝试编写一个 user-defined type guard 来测试给定的值是否具有给定数组中的所有属性。
我正在调用此函数 hasAll
,它在 Javascript 中的实现和用法如下所示:
function hasAll(obj, keysToCheck) {
if (!obj) return false;
for (const key of keysToCheck) {
const value = obj[key];
if (value === null) return false;
if (value === undefined) return false;
}
return true;
}
hasAll({ foo: 'test', bar: 5 }, ['foo', 'bar']); // true
hasAll({ foo: 'test', bar: 5 }, ['foo', 'bar', 'baz']); // false
我现在要做的是将上面的函数变成type guard。这是我目前所拥有的:
// this _almost_ works
type Nullable<T> = T | null | undefined;
type RemoveNullables<T, K extends keyof T> = {
[P in K]-?: T[P] extends Nullable<infer U> ? U : T[P];
};
function hasAll<T, K extends keyof NonNullable<T>>(
obj: T,
keysToCheck: K[],
): obj is RemoveNullables<NonNullable<T>, K> {
// but i'm getting an error here
if (!obj) return false;
const nonNullableObj = obj as NonNullable<T>;
for (const key of keysToCheck) {
const value = nonNullableObj[key];
if (value === null) return false;
if (value === undefined) return false;
}
return true;
}
export default hasAll;
错误信息是:
A type predicate's type must be assignable to its parameter's type.
Type 'RemoveNullables<NonNullable<T>, K>' is not assignable to type 'T'.
我已经阅读
我想明确声明我的类型T
在运行完这个函数后将符合RemoveNullables<NonNullable<T>, K>
。我真的不在乎 T
是否可以分配给 RemoveNullables<NonNullable<T>, K>
(如果有意义的话)。
- 我做错了吗?有没有更好的方法来编写这种类型保护?
- 如果这种方法没问题,我怎么能告诉打字稿我不在乎类型保护本身是否是 "unsafe"?
这似乎符合您的要求:
type ExcludeNullable<T, K extends keyof NonNullable<T>> = NonNullable<T> & {
[k in K]-?: Exclude<NonNullable<T>[k], null | undefined>
}
function hasAll<T, K extends keyof NonNullable<T>>(
obj: T,
keysToCheck: K[]
): obj is ExcludeNullable<T, K> {
return obj !== null && obj !== undefined
&& keysToCheck.every(k => obj![k] !== null && obj![k] !== undefined);
}
一些注意事项:
T & ...
交集类型保证ExcludeNullable<T, K>
可分配给T
。没有这个,映射类型就没有K
. 中缺少的 Exclude
是一种更简单的方法来摆脱null
和undefined
比使用带有infer
. 的条件类型
- 我冒昧地稍微简化了
hasAll
函数的实现。
T
属性