특정 키를 담은Attributes
인터페이스를 활용하여 AttributeGetters
를 완성하여 아래 테스트를 만족해야 한다.
가장 먼저 생각할 수 있는 것은 Record
다.
하지만 age
가 number 타입이기에 적절한 타입이 아니다. (유니언을 사용하게 되면 타입 가드가 필요하기 때문에 복잡도가 증가한다)
위에 대한 해답은 맵핑된 타입으로 처리하는 것이다.
Attributes
keyof
하여 키 타입을 생성하고, K
로 해당 타입을 맵핑해서 가져오면 된다.
테스트는 통과된다.
그렇다면 아래 테스트에서 객체의 키를 변경하면 어떻게 될까
키값이 변경되었을 때 키값을 재맵핑하는 방법으로는 리터럴 타입을 사용하면 된다.
하지만 getFirstname
처럼 대문자 변경이 안된 것을 확인할 수 있다. 이때 Capitalize
를 사용하면 된다.
이제 AttributeGetters
부분을 수정해준다.
하지만 타입을 확인해보면 unknown
으로 나오는 것을 확인 할 수 있다.
왜냐하면 당연하게도 여기서 K
는 Attributes
의 K
가 아니기 때문이다.
그렇기 때문에 Attributes
를 순회하여 K
를 사용해야 한다.
그리고 변경된 키로 수정하기 위해서 as
로 재맵핑을 한다.
이렇게 재맵핑을 하면 기존의 타입을 수정하지 않아도 테스트가 통과된다.
비동기 함수를 받아서 try catch
를 수행하는 safeFunction
이라는 함수가 있다.
위 함수에서 인자의 타입인 PromiseFunc
의 타입을 완성해야 한다.
func
함수는 Promise<Error | {제네릭한 리턴값}>
을 리턴해야 한다.
일단 PromiseFunc
를 제네릭으로 받는다.
그리고 safeFunction
을 제네릭하게 만든다.
이제 func
의 리턴 타입이 정확하게 나오는 걸 확인할 수 있다.
제네릭한 인자들의 타입을 설정하는 상황은 어떨까. 3번의 상황에서 args
라는 여러 인자들이 들어온다.
3번의 상황(인자가 없는)을 만족하면서 여러 인자가 들어오는 상황에 대해 타입을 어떻게 작성하면 될까.
먼저, args
의 타입도 제네릭 타입으로 받는다. TArgs
라 명명한다.
그럼 rest 매개 변수는 배열 형식이라는 타입 에러가 나온다. 그럼 제네릭으로 받은 TArgs
에 extends
를 해주면 된다.
그리고 동일하게 safeFunction
의 타입에서 TArgs
를 받아준다.
그럼 아래와 같은 타입 에러가 나온다.
이제 safeFunction
의 인자 ...args
의 타입을 TArgs
로 받으면 된다.
아래와 같이 제대로 된 타입을 보여준다.
그렇다면 왜 TArgs[]
로 받지 않고 TArgs
로 인자를 받고 extends any[]
로 제네릭하는 것일까?
각 인자의 타입이 같다고 확신할 수 없어 function type의 parameter는 tuple이기 때문이다.
아래는 function type의 parameter는 tuple 예시
그렇기 때문에 제네릭한 함수 타입의 인자 타입인 경우 extends any[]
로 받아줘야 한다.
참고 : totalTypescript