크고 작은 문제들/어려움

[TypeScript] 배열 반복문 내 타입 가드 오작동

노새두마리 2023. 12. 27. 14:51

요약

한 번에 여러 단계를 연속적으로 인덱싱하는 부분에 대하여 단계적으로 접근할 수 있도록 변경합니다.

type Obj = {
    a: number,
    b?: number[]
}

const arr: Obj[] = [{a: 1, b: [1]}, {a: 2}, {a: 3}];

// before
for (let i = 0; i < arr.length; i++){
    if (arr[i].b !== undefined){
    	arr[i].b ; // undefined일 수 있다는 경고 출력
    }
}

// after
for (let i = 0; i < arr.length; i++){
    const obj = arr[i];
    if (obj.b !== undefined){
    	obj.b; // 경고 미출력
    }
}

타입스크립트 플레이그라운드

위와 동일한 코드를 입력해 놓았습니다.

before 코드 블록의 arr[i].b에 커서를 올리시면 number[] | undefined, after 코드 블록의 obj.b에 커서를 올리시면 number[]로 추론되는 것을 확인하실 수 있습니다.


문제

result라는 빈 객체를 만들고 parameters 배열을 순회하면서 { [parameter.name]: 값 } 형태로 객체를 채워서 반환하는 함수입니다.

조건문을 통해 parameters[i].availableValues 배열이 있는지 확인하였음에도 타입스크립트는 값이 undefined일 수 있는 가능성에 대한 우려를 표출했습니다.

const createInitialState = (parameters: Parameter[]) => {
  const result: { [x: string]: string } = {};
  for (let i = 0; i < parameters.length; i++) {
    if (parameters[i].availableValues !== undefined) {
      result[parameters[i].name] = parameters[i].availableValues[0] ?? "";
    } else {
      result[parameters[i].name] = "";
    }
  }
};

parameters > i번째 인덱스 접근 > availableValues

처음 작성한 코드에서는 한 번에 두 단계를 접근하였습니다.


해결

타입 가드 수행 직전에 한 단계만 거칠 수 있도록 parameters[i]를 변수 parameter에 할당하는 과정을 추가하였습니다.

const createInitialState = (parameters: Parameter[]) => {
  const result: { [x: string]: string } = {};
  for (let i = 0; i < parameters.length; i++) {
    const parameter = parameters[i];
    if (parameter.availableValues !== undefined) {
      result[parameter.name] = parameter.availableValues[0];
    } else {
      result[parameter.name] = "";
    }
  }
};

이제 타입스크립트는 만족스러워 합니다.


핵심

한 번에 데이터의 여러 단계를 인덱싱하면 조건문을 이용한 타입 가드 적용이 의도대로 작동하지 않을 수 있습니다.