typescript - 为什么我会丢失属性在此映射类型中是否可选

标签 typescript typescript2.0 mapped-types

我有一个映射类型 Minus<A,B>用于创建具有 A 上所有属性的类型,但 B 上的属性除外,定义如下:

type Diff<T extends string, U extends string> = ({[P in T]: P } & {[P in U]: never } & { [x: string]: never })[T];

/**
 * Type T without any of the properties on U.
 */
export type Minus<T, U> = {[P in Diff<keyof T, keyof U>]: T[P]};

例如,如果我有两个接口(interface),A

interface A {
    thing1: string;
    thing2: number;
}

B

interface B {
    thing1: string;
}

然后 Minus<A, B>应该产生等同于

的类型
interface C {
    thing2: number;
}

在我在 A 上有可选类型之前,这很有效,因为这些在途中某处丢失了。

替换 A

interface A {
    thing1: string;
    thing2?: number;
}

将导致一个看起来像的类型

interface C {
    thing2: number;
}

而不是想要的

interface C {
    thing2?: number;    
}

有趣的是,Readonly<T> 的行为似乎确实保留了属性是否可选; Readonly 将产生一个等同于

interface ReadonlyA {
    readonly thing1: string;
    readonly thing2?: number;
}

所以我怀疑这与我的 Diff 类型有关。

有没有人有一个解决方案可以在 A 上保留属性是否可选? ?

最佳答案

解决方案是重新定义 Minus<A, B>成为

type Diff<T extends string, U extends string> = ({[P in T]: P } & {[P in U]: never } & { [x: string]: never })[T];

/**
 * Type T without any of the properties on U.
 */
export type Minus<T, U> = Pick<T, Diff<keyof T, keyof U>>;

这将正确保留可选类型。

归功于 Daniel Khoroshko为我指出正确的方向

关于typescript - 为什么我会丢失属性在此映射类型中是否可选,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47899627/

相关文章:

javascript - 想要在 javascript 中编写正则表达式,它将检查所有提到的字符是否至少存在

typescript - 如何通过 TypeScript 中的映射类型删除属性

typescript - 如何让 TypeScript 查找类型在这种情况下工作?

TypeScript 和可选的解构参数

angular - 在模板文件中使用环境变量

angular - 无法解析 ngrx/store 操作的所有参数

typescript - tsc - 忽略命令行错误

typescript - 映射类型时省略只读属性

typescript - 如何使用 fetchApi angular2 TYpescript 在 View 中绑定(bind) Ajax 结果?

TypeScript:选择具有定义类型的属性