awesome-typescript icon indicating copy to clipboard operation
awesome-typescript copied to clipboard

「重学TS 2.0 」TS 练习题第四十六题

Open semlinker opened this issue 3 years ago • 5 comments

实现 RequireAllOrNone 工具类型,用于满足以下功能。即当设置 age 属性时,gender 属性也会变成必填。具体的使用示例如下所示:

interface Person {
  name: string;
  age?: number;
  gender?: number;
}

type RequireAllOrNone<T, K extends keyof T> = // 你的实现代码

const p1: RequireAllOrNone<Person, 'age' | 'gender'> = {
  name: "lolo"
};

const p2: RequireAllOrNone<Person, 'age' | 'gender'> = {
  name: "lolo",
  age: 7,
  gender: 1
};

请在下面评论你的答案

semlinker avatar Oct 12 '21 10:10 semlinker

interface Person {
  name: string;
  age?: number;
  gender?: number;
}

type RequireAllOrNone<T, K extends keyof T> = Omit<T, K> & (Required<Pick<T, K>> | Partial<Record<K, never>>)

const p1: RequireAllOrNone<Person, "age" | "gender"> = {
  name: "lolo"
};

const p2: RequireAllOrNone<Person, "age" | "gender"> = {
  name: "lolo",
  age: 7,
  gender: 1
};

const p3: RequireAllOrNone<Person, "age" | "gender"> = {
// const p3: SetRequired<Person, "age" | "gender"> = {
// const p3: Omit<Person, "age" | "gender"> = {
  name: "lolo",
  age: 7,
};

思路: 巧妙利用 never 和 可选。

zhaoxiongfei avatar Oct 13 '21 02:10 zhaoxiongfei

秒啊,但是有个问题啊,partial会把值变成 never | undefined , 最终就是undefined。因此{ name: "lolo", age: undefined } 这样写也不会报错

s1pz avatar Oct 22 '21 06:10 s1pz

type RequireAllOrNone<T, K extends keyof T> = Omit<T, K> & ({ [P in K]-?: T[P] } | { [P in K]?: never })

jackwangwj avatar Dec 17 '21 06:12 jackwangwj

type Readonly<T> = {
     readonly [P in keyof T] -?: T[P]
  }

  type RequireAllOrNone<T, K extends keyof T> = Readonly<Pick<T, K>> & Omit<T, K>
···

dentm avatar Jun 24 '22 08:06 dentm

type RequireAllOrNone<T, K extends keyof T> =
  | (Omit<T, K> & Required<Pick<T, K>>)
  | { [Key in keyof T]: Key extends K ? never: T[Key] };

zhengyimeng avatar Nov 14 '22 08:11 zhengyimeng