2757 - PartialByKeys
문제: 두 개의 타입 인수
T
와 K
를 사용하는 PartialByKeys<T, K>
를 구성하세요. K
는 옵셔널하며 T
의 프로퍼티로 이루어진 유니언 타입을 지정할 수 있습니다. K
를 제공하지 않는다면 Partial<T>
와 같이 모든 프로퍼티를 옵셔널하게 만들어야 합니다./* _____________ 여기에 코드 입력 _____________ */ // type PartialByKeys<T, K> = {[Index in keyof T as (Index extends K ? Index : never)]+?: T[Index]} & {[Index in keyof T as (Index extends K ? never : Index)]: T[Index]} type IterateObject<T> = {[K in keyof T]: T[K]} type PartialByKeys<T, K extends keyof T = keyof T> = IterateObject<{[Index in keyof T as (Index extends K ? Index : never)]+?: T[Index]} & {[Index in keyof T as (Index extends K ? never : Index)]: T[Index]}> type Test = keyof User /* _____________ 테스트 케이스 _____________ */ import type { Equal, Expect } from '@type-challenges/utils' interface User { name: string age: number address: string } interface UserPartialName { name?: string age: number address: string } interface UserPartialNameAndAge { name?: string age?: number address: string } type cases = [ Expect<Equal<PartialByKeys<User, 'name'>, UserPartialName>>, Expect<Equal<PartialByKeys<User, 'name' | 'age'>, UserPartialNameAndAge>>, Expect<Equal<PartialByKeys<User>, Partial<User>>>, // @ts-expect-error Expect<Equal<PartialByKeys<User, 'name' | 'unknown'>, UserPartialName>> ]
- 풀이
&
인터섹션 연산은 의도와 다르게 풀이 되므로 Iterate 해주는 타입으로 래핑하는 것이 필요했다.
2759 - RequiredByKeys
문제: Implement a generic
RequiredByKeys<T, K>
which takes two type argument T
and K
. K
specify the set of properties of T
that should set to be required. When K
is not provided, it should make all properties required just like the normal Required<T>
./* _____________ 여기에 코드 입력 _____________ */ type IterateObject<T> = {[K in keyof T]: T[K]} type RequiredByKeys<T, K extends keyof T = keyof T> = IterateObject<{[Index in keyof T as Index extends K ? Index : never]-?: T[Index]} & {[Index in Exclude<keyof T, K>]?: T[Index]}> /* _____________ 테스트 케이스 _____________ */ import type { Equal, Expect } from '@type-challenges/utils' interface User { name?: string age?: number address?: string } interface UserRequiredName { name: string age?: number address?: string } interface UserRequiredNameAndAge { name: string age: number address?: string } type cases = [ Expect<Equal<RequiredByKeys<User, 'name'>, UserRequiredName>>, Expect<Equal<RequiredByKeys<User, 'name' | 'age'>, UserRequiredNameAndAge>>, Expect<Equal<RequiredByKeys<User>, Required<User>>>, // @ts-expect-error Expect<Equal<RequiredByKeys<User, 'name' | 'unknown'>, UserRequiredName>>, ]
- 배운 점
- -? 를 통해 optional 을 제거할 수 있다.
2793 - Mutable
문제: Implement the generic
Mutable<T>
which makes all properties in T
mutable (not readonly)./* _____________ 여기에 코드 입력 _____________ */ type Mutable<T extends object> = {-readonly [K in keyof T]: T[K]} /* _____________ 테스트 케이스 _____________ */ import type { Equal, Expect } from '@type-challenges/utils' interface Todo1 { title: string description: string completed: boolean meta: { author: string } } type List = [1, 2, 3] type cases = [ Expect<Equal<Mutable<Readonly<Todo1>>, Todo1>>, Expect<Equal<Mutable<Readonly<List>>, List>>, ] type errors = [ // @ts-expect-error Mutable<'string'>, // @ts-expect-error Mutable<0>, ]
- 배운 점
- - readonly 로 뺄 수 있음
2852 - OmitByType
문제: From
T
, pick a set of properties whose type are not assignable to U
./* _____________ 여기에 코드 입력 _____________ */ type OmitByType<T, U> = {[K in keyof T as T[K] extends U ? never : K]: T[K]} type Test = OmitByType<Model, boolean> /* _____________ 테스트 케이스 _____________ */ import type { Equal, Expect } from '@type-challenges/utils' interface Model { name: string count: number isReadonly: boolean isEnable: boolean } type cases = [ Expect<Equal<OmitByType<Model, boolean>, { name: string, count: number }>>, Expect<Equal<OmitByType<Model, string>, { count: number, isReadonly: boolean, isEnable: boolean }>>, Expect<Equal<OmitByType<Model, number>, { name: string, isReadonly: boolean, isEnable: boolean }>>, ]
- 배운 점
- K 자체를 타입 연산의 결과로 사용할 수 있다.
2946 - ObjectEntries
문제: Implement the type version of
Object.entries
/* _____________ 여기에 코드 입력 _____________ */ type InnerDistributer<T, K extends keyof T = keyof T> = K extends any ? [K, T[K]] : never; export type ObjectEntries<T> = InnerDistributer<T> type Dental = ObjectEntries<Partial<Model>> /* _____________ 테스트 케이스 _____________ */ import type { Equal, Expect } from '@type-challenges/utils' interface Model { name: string age: number locations: string[] | null } type ModelEntries = ['name', string] | ['age', number] | ['locations', string[] | null] type cases = [ Expect<Equal<ObjectEntries<Model>, ModelEntries>>, Expect<Equal<ObjectEntries<Partial<Model>>, ModelEntries>>, Expect<Equal<ObjectEntries<{ key?: undefined }>, ['key', undefined]>>, Expect<Equal<ObjectEntries<{ key: undefined }>, ['key', undefined]>>, Expect<Equal<ObjectEntries<{ key: string | undefined }>, ['key', string | undefined]>>, ]
- 풀이
- 배열의 유니온 형태로 return 이 되어야 하므로 분배 조건부 연산이 필요하다.
- 각 key 와 그에 맞는 타입이 같이 배열에 들어가야하므로 새로운 제네릭 인자 K 를 넣고 기본값으로
keyof T
를 추가한다. - K 자리에 뭔가 들어가면 안 되므로, 래퍼 타입을 만든다.
3062 - Shift
문제: Implement the type version of
Array.shift
/* _____________ 여기에 코드 입력 _____________ */ type Shift<T extends unknown[]> = T extends [infer _, ...infer Rest] ? Rest : T; /* _____________ 테스트 케이스 _____________ */ import type { Equal, Expect } from '@type-challenges/utils' type cases = [ // @ts-expect-error Shift<unknown>, Expect<Equal<Shift<[]>, []>>, Expect<Equal<Shift<[1]>, []>>, Expect<Equal<Shift<[3, 2, 1]>, [2, 1]>>, Expect<Equal<Shift<['a', 'b', 'c', 'd']>, ['b', 'c', 'd']>>, ]