주어진 인터페이스에 새로운 필드를 추가한 object 타입을 구현하세요. 이 타입은 세 개의 인자를 받습니다.
type AppendToObject<T extends object, U extends string|number|symbol, V> =
{ [R in (keyof T)|U] :R extends U? V: R extends keyof T ? T[R]:never }
mapped type을 이용하여 구현하였다. U 제네릭을 잘 사용하기 위해 타입 제한을 두었다.
type AppendToObject<T, U extends keyof any, V> = {
[K in keyof T | U]: K extends keyof T ? T[K] : V;
};
조금 더 간결한 풀이다. keyof any로 U에 대한 제한을 주었다.
그러나 이 풀이는 U가 T에 들어가있으면, 덮어쓰여진다는 점이 다르다.
type AppendToObject<T extends object, U extends keyof any, V> =
T&{[R in U]:V}
이 타입은 왜 정답이 되지 못할까?
그 이유는 intersection(&) 연산자에 있다.
두 타입의 차이는 U가 기존 keyof T에 속할 때 나타난다.
정답으로 처리된 타입에서는 U가 기존 keyof T에 속한다면 U를 무시하거나, 덮어쓰는 방식으로 답을 처리한다.
그러나 &를 이용하게 된다면 겹치는 타입에 대한 밸류 타입은 never가 된다.
type test1 = {
key: 'cat'
value: 'green'
}
type test2={
value:number
}
type test3=test1&test2
// type test3={
// key:'cat'
// value:never
// }
문제에서는 U가 기존 keyof T에 속할 때에 대한 정답을 제공하지 않기 때문에 별 차이가 없지만,
문제에서 채점을 위해 제공하는 Equal 타입에서는, U가 keyof T에 속할 때의 차이점을 인식한다.
https://github.com/type-challenges/type-challenges/issues/536
https://www.typescriptlang.org/docs/handbook/2/objects.html#interface-extension-vs-intersection