개발자

타입스크립트 'value' is possibly 'null' 에러 옵셔널체이닝으로 해결안되는 이슈

2024년 03월 24일조회 261

import DateRangePicker from "@wojtekmaj/react-daterange-picker"; import { useDispatch } from "react-redux"; import { dateFetch } from "components/feature/FetchSlice"; import styled from "styled-components"; type ValuePiece = Date | null; type Value = ValuePiece | [ValuePiece, ValuePiece]; export default function CustomCalendar() { const dispatch = useDispatch(); const [value, onChange] = useState<Value>([new Date(), new Date()]); return ( <CalendarBox> <Calendar>조회 기간</Calendar> <StlyedDateRangePicker onChange={onChange} value={value} onCalendarClose={() => { dispatch( dateFetch({ startDate: value[0]?.toISOString(), endDate: value[1]?.toISOString(), }) ); console.log(value); }} /> </CalendarBox> ); } <StlyedDateRangePicker>는 styled component로 만든 DateRangePicker 라이브러리 컴포넌트입니다. DateRangePicker 에서 날짜 2개를 선택하면 value라는 배열에 Date 객체 2개가 들어갑니다. 그리고 onCalendarClose 함수가 동작하면서 redux로 만들어놓은 startDate, endDate 객체에 각각 date를 toISOString() 처리한 값이 할당되는 로직입니다. 날짜를 선택하기 전에는 value={value}의 value 배열요소인 Date객체 값이 null 값이니까 type ValuePiece = Date | null; 타입지정을 해줬습니다. startDate: value[0]?.toISOString(), endDate: value[1]?.toISOString(), 근데 위 코드의 value[0], value[1] 에러가 나더라구요. 'value' is possibly 'null'.ts(18047) Element implicitly has an 'any' type because expression of type '0' can't be used to index type 'Date | [ValuePiece, ValuePiece]'. Property '0' does not exist on type 'Date | [ValuePiece, ValuePiece]'. null 값일 수도 있다길래 옵셔널체이닝을 줬는데 여전히 에러가 발생합니다.. 해결방법을 도무지 모르겠네요.. 도와주시면 진심으로 감사하겠습니다ㅠㅠㅠ

이 질문이 도움이 되었나요?
'추천해요' 버튼을 누르면 좋은 질문이 더 많은 사람에게 노출될 수 있어요. '보충이 필요해요' 버튼을 누르면 질문자에게 질문 내용 보충을 요청하는 알림이 가요.
profile picture
익명님의 질문

답변 3

인기 답변

민경배님의 프로필 사진

안녕하세요! 타입스크립트가 워낙 까다로운 언어이다보니 많은 고민이 있으셨을 것 같네요! 근본적으로는 현재 value의 타입이 잠재적으로 null | Date | [ Date | null, Date | null ] 형태의 어레이와 결합된 복잡한 형태를 띄고 있기 때문에, 이러한 구조 자체가 TS에서 어느정도 지양해야할 패턴으로 보입니다. 하지만 외부라이브러리를 쓰시는 것으로 보여서 감수하고 해결 가능한 답변을 생각해보겠습니다! 먼저 질문자님께서 시도하셨던 방식에서 value는 array일 수도, 아닐 수도 있기 때문에 0번, 1번 인덱스에 접근하고자 하는 시도 자체가 타입에러를 내고 있는 듯 합니다. 따라서 이를 방지하기 위해, 먼저 타입가드 / 조건문 등의 방식을 통해 array형태 여부를 걸러서 케이싱을 해준다면 더 안전한 코드 작성이 가능해 보입니다. 작성시엔 여러 방식이 있지만, 코드의 가독성면에서 제일 좋아보이는 타입가드 코드를 첨부해두겠습니다!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 타입가드 함수
function isValuePieceArray(value: Value): value is [ValuePiece, ValuePiece] {
  return Array.isArray(value);
}

const onCalendarClose = () => {
  if (isValuePieceArray(value)) {
    // value가 [ValuePiece, ValuePiece] 인 경우
    dispatch(
      dateFetch({
        // 필요에 따라 Nullish Coalescing 추가
        startDate: value[0]?.toISOString(),
        endDate: value[1]?.toISOString(),
      }),
    );
  } else {
    // value가 ValuePiece인 경우
    ...
  }
};
profile picture

익명

작성자

2024년 03월 27일

오 알려주신대로 해보니 해결됐어요!!! startDate, endDate 타입을 string | undefined 로 설정하고 알려주신대로 onCalendarClose함수를 새로 만들고 타입가드 함수를 적용시키니 해결됐습니다. 정말 감사합니다!!

포크코딩님의 프로필 사진

첫 번째 방안: dispatch 호출 전에 조건 문을 통한 타입 강제 및 체크 두 번째 방안: as 키워드 사용 세 번째 방안: Option, Either 같은 모나드를 사용한 패턴 매칭

profile picture

익명

작성자

2024년 03월 27일

시도해보진 않았지만 답변 감사합니다!!

장성호님의 프로필 사진

type ValuePiece = Date | null; type Value = ValuePiece | [ValuePiece, ValuePiece]; 이부분에서 Value = (Date | null) | [(Date | null), (Date | null)]; 로 풀이되어서 Null 일 가능성이 있다고 하는 것 아닐까요? 그리고 배열이 아니라 단순한 Date일 가능성도 있어서, 인덱스를 통한 접근은 Date 타입에 사용할 수 없다고 이야기하는 것 같아요! DateRangePicker에서 범위가 한 날짜에 해당하거나, 여러 날짜에 해당하는 경우 나눠서 조건문으로 타입체크하는게 좋아보입니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 배열에 대한 타입가드
function isArrayOfType<T>(arr: any[], type: new (...args: any[]) => T): arr is T[] {
  return arr.every(item => item instanceof type);
}

// 단일 날짜
var value = new Date(2024, 3, 25);

// 여러 날짜
// var value = [new Date(2024, 3, 24), new Date(2024, 3, 25)]

// 타입이 맞지 않음
// var value = [new Date(2024, 3, 24), null]

if(value instanceof Date) {
  console.log("Date");
} else if (isArrayOfType(value, Date)) { 
  console.log("Array");
} else {
  console.log("TYPE NOT MATCHED");
}
profile picture

익명

작성자

2024년 03월 27일

시도해보진 않았지만 답변 감사합니다!!

지금 가입하면 모든 질문의 답변을 볼 수 있어요!

현직자들의 명쾌한 답변을 얻을 수 있어요.

또는

이미 회원이신가요?

목록으로
키워드로 질문 모아보기

실무, 커리어 고민이 있다면

새로운 질문 올리기

지금 가입하면 모든 질문의 답변을 볼 수 있어요!