타입좁히기
: 변수 또는 표현식의 타입 범위를 더 작은 범위로 좁혀나가는 과정
.
.
.
타입스크립트에서의 분기 처리
: 조건문과 타입 가드를 활용하여 변수나 표현식의 타입 범위를 좁혀 다양한 상황에 따라 다른 동작을 수행하는 것.
타입가드
: 런타임에 조건문을 사용 -> 타입 검사, 타입 범위를 좁혀주는 기능
스코프
: 변수와 함수 등의 식별자identifier가 유효한 범위
( 변수와 함수를 선언하거나 사용할 수 있는 영역 )
ex) A | B 타입의 매개변수를 받을 때
if문을 사용해서 처리?
: 컴파일 시 타입 정보는 모두 제거 -> 런타임에 존재하지 않음 -> 타입 사용 조건문 제작 x
=> 컴파일해도 타입 정보가 사라지지 않을 방법을 사용해야 한다.
틀정 문맥 안 타입스크립트가 해당 변수를 타입 A로 추론하도록 유도 & 런타임에서도 유효해야 함. -> 이때 타입가드를 사용
1) 자바스크립트 연산자를 활용한 타입 가드
: typeof, instanceof, in과 같은 연산자 사용
제어문으로 측정 타입 값을 가질 수 밖에 없는 상황을 유도
-> 자연스레 타입 좁히기 & 런타입에 유효
2) 사용자 정의 타입 가드
: 사용자가 직접 어떤 타입으로 값을 좁힐지 직접 지정
typeof 연산자 활용 -> 원시 타입에 대해 추론
typeof A === B 조건 분기 처리 -> 해당 분기 내 A의 타입이 B로 추론
복잡한 타입 검증에는 한계
-> typeof 연산자는 주로 원시 타입을 좁히는 용도로만 사용할 것을 권장.
const replaceHyphen: (date: string | Date) => string | Date = (date) => {
if (typeof date === "string") {
// 이 분기에서는 date의 타입이 string으로 추론된다
return date.replace(/-/g, "/");
}
return date;
};
interface Range {
start: Date;
end: Date;
}
interface DatePickerProps {
selectedDates?: Date | Range;
}
const DatePicker = ({ selectedDates }: DatePickerProps) => {
const [selected, setSelected] = useState(convertToRange(selectedDates));
//...
};
export function convertToRange (Selected?: Date, Range): Range | undefined {
return selected instanceof Date
? { start: selected, end: selected }
: selected;
}
typeof 연산자 : 주로 원시 타입 판별
instanceof 연산자 : 인스턴스화된 객체 타입을 판별하는 타입 가드로 사용
A instanceof B
A : 타입을 검사할 대상 변수
B : 특정 객체의 생성자
유의) A의 프로토타입 속성 변화 에 따라 instanceof 연산자의 결과가 달라질 수 있음.
const onKeyDown = (event: React.KeyboardEvent) => {
if (event.target instanceof HIMLInputElement && event.key === "Enter") {
// 이 분기에서는 event.target의 타입 HTMLInputELement 이며
// event.key가 'Enter'이다.
event.target.blur();
OnCTABut tonClick(event);
}
};
: HIMLInputElement에 존재하는 blur메서드 사용하기 위해 event.target이 HIMLInputElement의 인스턴스인지를 검사하는 준기 처리하는 로직
in연산자는 객체에 속성이 있는지 확인 -> true or false 반환
( 속성이 있는지 없는지에 따라 객체 타입을 구분 )
A in B
A라는 속성이 B객체에 존재하는 지 검사
true : 프로토타입 체인으로 접근할 수 있는 속성
false : delete연산자를 사용하여 객체 내부에 해당 속성을 제거해야 함.
( B 객체에 존재하는 A 속성에 undefined 할당한다고 false x )
interface BasicNoticeDialogProps {
noticeTitle: string;
noticeBody: string;
}
interface NoticeDialogWithCookieProps extends BasicNoticeDialogProps {
cookieKey: string;
noForADay?: boolean;
neverAgain?: boolean;
}
export type NoticeDialogProps =
| BasicNoticeDialogProps
| NoticeDialogWithCookieProps;
NoticeDialog 컴포넌트 : BasicNoticeDialogProps( 2가지 객체 타입의 유니온 타입 )를 props로 받음.
NoticeDialogProps ( 유니온 타입 ) : BasicNoticeDialogProps 객체 타입 + NoticeDialogWithCookieProps 객체 타입
=> 두 객체 타입을 cookieKey 속성을 가졌는지 아닌지에 다라 -> in 연산자로 조건 만들 수 있음
const NoticeDialog: React.FC <NoticeDialogProps> = (props) => {
if ("cookieKey" in props) return <NoticeDialogWithCookie {..props}/>;
return <NoticeDialogBase {props} />;
};
in 연산자 : 런타입의 값만을 검사, 타입스크립트에서는 객체 타입에 속서이 존재하는지를 검사.
if문 스코프 : 타입스크립트는 props 객체를 cookieKey속성을 간는 객체 타입인 NoticeDialogWithCookieprops로 해석.
얼리 리턴 Early Return했기 땜에 if문 스코프 밖에 위치하는 return문의 props 객체는 BasicNoticeDialogProps의 타입으로 해석함.
얼리 리턴 Early Return
: 특정 조건에 부합하지 않으면 바로 반환 return 하는 것.
=> 여러 객체 타입을 유니온 타입으로 가지고 있을 때 in 연산자를 사용해서 속성의 유무에 따라 조건 분기 가능
: 직접 타입 가드 함수 만들기
타입 명제 : A is B
A : 매개변수
B : 타입
참 / 거짓의 진릿값을 반환, 반환 타입을 타입 명제로 지정 -> 반환 값이 참일 때 A 매개변수의 타입을 B 타입으로 취급하게 됨.
타입 명제 type predicates
: 함수의 반환 타입에 대한 타입 가드를 수행하기 위해 사용되는 특별한 형태의 함수
const isDestinationCode = (x: string): x is DestinationCode =>
destinationCodeList.includes(x);
const getAvailableDestinationNameList = async (): Promise <DestinationName[]> => {
const data = await AxiosRequest<string[]>("get", ".../destinations");
const destinationNames: DestinationName[] = [];
data?.forEach((str) => {
if (isDestinationCode(str)) {
destinationNames.push(DestinationNameSet[str]);
/*
isDestinationcode의 반환 값에 is를 사용하지 않고 boolean이라고 한다면 다음 에러가 발생한다.
- Element implicitly has an any type because expression of type 'string'
can't be used to index type 'Record <"MESSAGE PLATFORN"|"COUPON PLATFORM" | "BRAZE",
"통합메시지플랫폼" | "쿠폰대장간" | "braze">'
*/
}
});
return destinationNames;
};
if문 내 isDestinationCode 함수로 data의 strdl isDestinationCode
도서참조 : 우아한 타입스크립트 with 리액트