인프런 커뮤니티 질문&답변

enhan님의 프로필 이미지
enhan

작성한 질문수

실전 프로젝트로 배우는 타입스크립트

타입 구조를 어떤식으로 줘야하는지 궁금합니다.

작성

·

186

1

reduce를 사용하는데 타입 지정에 대해 어려움을 느끼고 있습니다.


// people은 내가 아는 정보만 넣었기 때문에, 타입이 같은것도 있지만, 대부분 다릅니다.
const people = {
home: [
{
name: '홍길동',
age: 45,
relationship: 'father',
gender: 'man',
},
{
name: '김길순',
age: 42,
relationship: 'mather',
},
],
school: [
{
name: '둘리',
age: 45,
relationship: 'teacher',
height: 170,
},
{
name: '마이콜',
age: 21,
relationship: 'friend',
gender: 'man',
},
],
};

type LocationType = keyof typeof people;

// 함수의 인자로 people 객체의 'home' or 'school' 만 받습니다.
const peopleFunction = (location: LocationType) => {
// selectLocation에는 people에 home 또는 school이 들어간 상태라고 생각하고 있습니다.
const selectLocation = people[location];

// 나는 모든 객체의 공통으로 있는 name와 age만 빼오고 싶습니다. 하지만 아래 reduce에서 에러가 납니다.
const answer = selectLocation.reduce((acc, cur) => {
acc[cur.name] = {
name: cur.name,
age: cur.age,
};
}, {});

return null;
};

어떤식으로 해결해야할까요?

 

답변 2

0

enhan님의 프로필 이미지
enhan
질문자

타입가드를 많이쓰게 되면, 타입스크립트 쓰던 이전의 느낌이 나서 지양하려고 하고있었는데,

뭐든 잘 써봐야겠네요..ㅠ

우선 함수 시작할때즈음에, 타입가드로 타입을 잡아주고 진행을 하는것이 하나의 풀이법이라고 말씀해주신것이 맞으실까요?

적어 주신 isSchool안에 제가 원하는 reduce를 진행하면 되는걸까요?

if (isSchool(selectLocation)) {

return;

}

또한, isPeople도 동일하게 진행 해줘야할까요?

사실 제가 school 과 people뿐만아니라, 한 10개정도가 더 있는상황이라, 하나하나 다 타입가드를 하기에는 조금 부담스럽다고 느끼고 있긴합니다.ㅠ

친절한 답변 정말 감사합니다. :)

0

안녕하세요 민한님, 좋은 질문 주셨네요 :) 첨부해주신 코드는 현재 타입스크립트 공식 리포지토리에 아래와 같은 이슈로 문제가 제기 되어 있습니다.

https://github.com/microsoft/TypeScript/issues/36390

여튼 꽤 복잡한 타입 추론 코드가 필요하기 때문에 가장 간단한 방법은 reduce()를 돌리는 대상 변수에 as 를 사용하시는게 좋을 것 같구요. 그 외에 타입 가드로 해당 reduce()의 not callable expression 문제를 해결하려면 아래와 같은 코드를 사용해 볼 수 있을 것 같습니다.

interface People {
home: Home[];
school: School[];
}

interface Home {
name: string;
age: number;
relationship: string;
gender?: string;
}

interface School {
name: string;
age: number;
relationship: string;
height?: number;
gender?: string;
}

function isSchool(target: Home[] | School[]): target is School[] {
return (target as School[]).every(t => t.height !== undefined);
}

const people: People = {
home: [
{ name: '홍길동', age: 45, relationship: 'father', gender: 'man' },
{ name: '김길순', age: 42, relationship: 'mather' },
],
school: [
{ name: '둘리', age: 45, relationship: 'teacher', height: 170 },
{ name: '마이콜', age: 21, relationship: 'friend', gender: 'man' },
],
};

type LocationType = keyof typeof people;

// 함수의 인자로 people 객체의 'home' or 'school' 만 받습니다.
const peopleFunction = (location: LocationType) => {
// selectLocation에는 people에 home 또는 school이 들어간 상태라고 생각하고 있습니다.

const selectLocation = people[location];
if (isSchool(selectLocation)) {
return;
}

// 나는 모든 객체의 공통으로 있는 name와 age만 빼오고 싶습니다. 하지만 아래 reduce에서 에러가 납니다.

const answer = selectLocation.reduce((acc, cur) => {
// TODO: 아래 문법은 리듀스의 문법 규칙에 어긋납니다. 반환 타입 보시고 올바른 값을 반환해 주세요.
// acc[cur.name] = {
// name: cur.name,

// age: cur.age,
// };
return acc;
}, {});

return null;
};
enhan님의 프로필 이미지
enhan

작성한 질문수

질문하기