yunliuyan / type-challenges

typescript-challenges
0 stars 2 forks source link

00004-medium-omit #4

Open yunliuyan opened 1 year ago

yunliuyan commented 1 year ago

实现 Omit 中等 #union #built-in

by Anthony Fu @antfu

接受挑战    English 日本語 한국어

不使用 Omit 实现 TypeScript 的 Omit<T, K> 泛型。

Omit 会创建一个省略 K 中字段的 T 对象。

例如:

interface Todo {
  title: string
  description: string
  completed: boolean
}

type TodoPreview = MyOmit<Todo, 'description' | 'title'>

const todo: TodoPreview = {
  completed: false,
}

测试案例:

import type { Equal, Expect } from '@type-challenges/utils'

type cases = [
  Expect<Equal<Expected1, MyOmit<Todo, 'description'>>>,
  Expect<Equal<Expected2, MyOmit<Todo, 'description' | 'completed'>>>,
]

// @ts-expect-error
type error = MyOmit<Todo, 'description' | 'invalid'>

interface Todo {
  title: string
  description: string
  completed: boolean
}

interface Expected1 {
  title: string
  completed: boolean
}

interface Expected2 {
  title: string
}

返回首页 分享你的解答 查看解答

相关挑战

4・实现 Pick
yunliuyan commented 1 year ago

思路

和pick取反就醒了

代码实现

type MyOmit<T, K> = {
    [key in keyof T as key extends K ? never : key]: T[key]
  }
wudu8 commented 1 year ago
type EasyOmit<T, U extends keyof T> = {
    [k in keyof T]: k extends U ? never : T[k];
};

interface OmitType {
    name: string;
    description: string;
    address: string;
}

const easyOmitTest: EasyOmit<OmitType, 'name' | 'description'> = {
    name: "字节猿", // Error: The expected type comes from property 'name' which is declared here on type 'EasyOmit<OmitType, "name" | "description">'
    description: "字节猿喜欢readonly", // Error: The expected type comes from property 'description' which is declared here on type 'EasyOmit<OmitType, "name" | "description">'
    address: "我家在陕西", // Ok
};

type error = EasyOmit<OmitType, 'name' | 'test'> // Error: Type '"test"' is not assignable to type 'keyof OmitType'
Janice-Fan commented 1 year ago

`type MyOmit<T, P extends keyof T> = {

}`

liangchengv commented 1 year ago
type MyOmit<T, K extends keyof T> = {
  [P in keyof T]: P extends K ? never : T[P];
};
Naparte commented 1 year ago
// 不使用 Omit 实现 TypeScript 的 Omit<T, K> 泛型。
// Omit 会创建一个省略 K 中字段的 T 对象。

type MyOmit<T, K extends keyof T> = {
    [key in keyof T as key extends K ? never : key]: T[key]
}

interface Todo4 {
    title: string
    description: string
    completed: boolean
    // test: never
}

type TodoPreview4 = MyOmit<Todo4, 'description' | 'title'>

const todo: TodoPreview4 = {
    completed: false,
    // test: false as never
}