typescript - 选择可空属性并使它们不可空的一般方法

标签 typescript

让我们有以下示例类型:

interface A {
    a?: number;
    b: string;
}

我的目标是使用一种通用的方式来创建以下类型:

interface ExpectedA {
    a: number;
}

所以我想删除所有不可为 null 的字段(那些可以包含 null 和/或 undefined 的字段)并使那些剩余的可为 null 的字段不可为 null。

这就是我想象的它应该如何工作:

const expA1: ExpectedA = {}; // should NOT pass
const expA2: ExpectedA = {a: 1}; // should pass
const expA3: ExpectedA = {b: ''}; // should NOT pass
const expA4: ExpectedA = {c: 0}; // should NOT pass
const expA5: ExpectedA = {a: 1, b: ''}; // should NOT pass

这是我的非工作尝试(在评论中注释它做了什么以及它应该做什么):

export type ExtractNullable<T> = {
    [K in keyof T]: T[K] extends undefined | null ? NonNullable<T[K]> : never;
};

const a1: ExtractNullable<A> = {}; // should NOT pass, wrong error "prop. b is missing"
const a2: ExtractNullable<A> = {a: 1}; // should pass, wrong - "number not undefined"
const a3: ExtractNullable<A> = {b: ''}; // should NOT pass, wrong - "string not never"
const a4: ExtractNullable<A> = {c: 0}; // should NOT pass, ok - "c not on ..."
const a5: ExtractNullable<A> = {a: 1, b: ''}; // should NOT pass, wrong error "number not undefined, string not never"

我认为问题出在条件类型上,但是查看文档,我不知道要更改什么。

最佳答案

您只需要先选择可为空的键,然后再映射它们。

interface A {
    a?: number;
    b: string;
}

export type NullableKeys<T> = {
    [P in keyof T]-? :  Extract<T[P], null | undefined> extends never ? never: P
}[keyof T]
export type ExtractNullable<T> = {
    [P in NullableKeys<T>]: NonNullable<T[P]>
}

const a1: ExtractNullable<A> = {}; // err
const a2: ExtractNullable<A> = {a: 1}; //ok
const a3: ExtractNullable<A> = {b: ''}; // err
const a4: ExtractNullable<A> = {c: 0}; // err
const a5: ExtractNullable<A> = {a: 1, b: ''}; //err

上述方法适用于 strictNullChecks,因为可选属性的类型已更改为包括 undefined。选择可选属性并在没有此编译器选项的情况下工作的版本是:

export type NullableKeys<T> = {
    [P in keyof T]-?:  Pick<T,P> extends Required<Pick<T, P>> ? never: P
}[keyof T]

关于typescript - 选择可空属性并使它们不可空的一般方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53102994/

相关文章:

javascript - 如何在 React 和 Typescript 中使用 useRef 钩子(Hook)和 getClientBoundingRect?

javascript - ES6 map : transform values

javascript - 如何在 Typescript 中声明 ES6 模块的类型?

javascript - 让 Meteor、Webstorm 和 Typescript 协同工作的最佳实践是什么?

typescript - 限制方法中的接口(interface)类型参数

reactjs - 使用 TypeScript react 和融合 js

javascript - 对象数组减少 typescript 错误: not assignable to parameter of type 'never'

javascript - 在 NextJS/React 中加载 Skeleton 实现

javascript - 函数列表上的 typescript 映射

typescript - 使用代码优先方法在 Nestjs 中创建突变