타입스크립트 뭔가 재미있다.
타입스크립트 기초 공부할때는 문법정도만 나열되어있어서 그래서 어쩌라고? 이걸 왜쓰지? 뭐가좋다는거지? 이게 무슨 문제를 해결한다는거지? 했는데 exercises 풀어보니까 알겠다. 역시 프리온보딩 듣기를 잘했다.. 100% 알아듣지 못해도 때려박다보면 깨달음이 온다.
아래와 같이 했는데 빨간줄은 사라졌지만 에러가 나온다.
힌트를 보니 함수 오버로드가 키워드이다...
export function filterPersons(persons: Person[], personType: string, criteria: Partial<Person>): Person[] {
return persons
.filter((person) => person.type === personType)
.filter((person) => {
let criteriaKeys = Object.keys(criteria) as (keyof Person)[];
return criteriaKeys.every((fieldName) => {
return person[fieldName] === criteria[fieldName];
});
});
}
함수 오버로딩
함수 이름은 같지만(로직이 비슷함) 매개변수 타입이 다른(매개변수가 다름) 다양한 경우를 지원하기 위한 개념이다.
내가 입력한 키워드로도 작동은 제대로 되는 것 같다.
그런데 error TS2344: Type 'false' does not satisfy the constraint 'true' 이런 에러가 뜨는 것을 보니 타입에 따라 필터링중 true가 아니라 false가 나올때가 문제인 것 같다.
person type이 'user'일때와 'admin'일때를 따로 함수 오버로딩을 통해 정의해야하는듯.
export function filterPersons(persons: Person[], personType: string, criteria: Partial<Person>): Person[] {}
이렇게 되어있으니까
export function filterPersons(persons: Person[], personType: 'user', criteria: Partial<Person>): User[] {}
export function filterPersons(persons: Person[], personType: 'admin', criteria: Partial<Person>): Admin[] {}
여기까지만 해도 테스트는 통과한다. 참고로 함수 오버로드를 하려면 function 키워드로 함수를 선언해야한다. 화살표함수는 익명함수라서 그런 게 아닐까 싶음. 오버로드하려면 이름은 알아야지(?)
그런데 레퍼런스를 보니 제네릭을 이용해서 함수를 하나 더 만들었다.
제네릭
타입을 매개변수처럼 사용하는 것을 제네릭이라고 한다.
선언할때는<T>
이렇게 해준다. T는 뭔가 했었는데 보니까 type을 명시한 것 같고, 리액트에서 props를 받을때 styles 이런식으로 뚫어놓듯이 타입 받을 자리를 뚫어놓는 거라고 이해가 된다.function firstElement<Type>(arr: Type[]) { return arr[0]; }
위 함수에서 배열을 받았다고 가정해보자. 배열의 구성요소의 타입에따라 Type이 받는 타입이 정해진다. string 배열이 들어온다면 Type은 string이 되는 것.
const getObjectKeys = <T>(obj: T) => Object.keys(obj) as (keyof T)[];
객체의 키를 받는 화살표함수이다.
criteria = {age: 23}이 매개변수로 들어가고
getObjectKeys = ["age"] 가 나온다.
export function filterPersons(persons: Person[], personType: 'user', criteria: Partial<User>): User[];
export function filterPersons(persons: Person[], personType: 'admin', criteria: Partial<Admin>): Admin[];
export function filterPersons(persons: Person[], personType: string, criteria: Partial<Person>): Person[] {
return persons
.filter((person) => person.type === personType)
.filter((person) => {
let criteriaKeys = Object.keys(criteria) as (keyof Person)[];
return criteriaKeys.every((fieldName) => {
return person[fieldName] === criteria[fieldName];
});
});
}
every
배열의 모든 요소가 제공된 함수에 의해 구현된 테스트를 통과하는지 여부를 테스트