扩展或覆盖类型字段

时间:2018-03-28 17:07:16

标签: typescript generics

我需要一个类型声明,授予value字段类型string,所有其他字段不变。我觉得这很简单并写了

type WithValue<T> = T & { value: string; }

不幸的是,在某些情况下,我需要Tany。这会导致问题 - WithValue<any>变成any如何覆盖any类型的属性?

考虑关注code

type WithValue<T> = T & { value: string; }

function f<T extends object>(x: T): WithValue<T> {
  return {...x as any, value: ""};
}

declare var x: any;

var y = f(x); // y is any
y.value = 1;  // no error

由于分配number而不是string,我希望最后一行是错误。

我还尝试了to omit字段,但这导致another problem

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

declare var z: WithValue<Omit<any, 'value'>>;
z.value = "";
z.value = 1; // Error - Correct
z.aghj = 0;  // Error - I don't want this error

1 个答案:

答案 0 :(得分:4)

如何以不同的方式定义您的类型:

type WithValue<T> = { [K in keyof T]: T[K] } & { value: string };

然后,使用它,它似乎符合您的标准:

declare const x: WithValue<any>;
declare const y: WithValue<{a?: number}>

x.value.charAt(0); // Okay, since x.value has type string.
x.asdf.whatever; // Okay, since x.asdf has type any.

x.value = 1; // Error: Type number not assignable to type string.

y.value.charAt(0) // Okay, since y.value has type string;
y.a // Inferred to have type number | undefined (since it's optional)

y.asdf.whatever // Error: asdf does not exist on type...