자바스크립트에서 NOT
!
연산자는false
를 의미한다. 반면 타입스크립트에선 이 느낌표!
연산자가 변수 뒤에 올 수 있다.if
문 등을 사용하지 않고 항상 유효한 값이 있다고 단언 할 때 사용한다.
<aside>
💡 ESLint 규칙에선 느낌표 연산자를 사용하면 null-checking mode의 혜택을 받지 못하기 때문에 권장하지 않는다. 대신 foo.bar && foo.bar...
AND 연산자 혹은 옵셔널 체이닝 사용을 권장한다. 느낌표 연산자를 꼭 사용해야 한다면 항상 유효한 값을 보장하는 변수에만 사용한다.
</aside>
변수 내부 값에 접근할 때 TS 컴파일러는 항상 null
undefined
인지 체크한다. 이때 if
문으로 타입 단언을(변수에 원하는 타입을 강제로 부여)을 할 수 있다.
매번 if
문 쓰는게 귀찮을 때 !
연산자를 사용할 수 있다. 그럼 해당 값이 null
이나 undefined
가 아니라고 단언해준다. 컴파일러에게 이 값은 절대 null
혹은 undefined
가 될 수 없으니 실행하라는 것과 비슷하다.
아래 코드의 콘솔을 실행하면 TS2531 에러가 발생한다. lastName
타입을 string
혹은 null
로 설정했기 때문에 해당 값이 null
일 수도 있어서 나오는 경고다.
interface User {
firstName: string;
lastName: string | null;
}
const user1: User = {
firstName: 'Cobain',
lastName: 'Kurt',
};
console.log(user1.lastName.toUpperCase())
// 에러! TS2531: Object is possibly 'null'.
아래처럼 lastName
뒤에 !
느낌표를 붙여서 항상 값이 존재한다고 단언하면 에러가 나오지 않는다.
console.log(user1.lastName!.toUpperCase()) // 'Kurt'
이와 비슷한 옵셔널 체이닝(변수뒤에 물음표 ?
연산자 사용)은 해당 값이 null
혹은 undefined
면 평가를 멈추고 undefined
를 반환하는 점이 다르다. 아래처럼 평가하는 값이 null
이나 undefined
일 수도 있을 땐 에러를 피하기 위해 옵셔널 체이닝을 사용한다.
const user1: ServiceUser = {
firstName: 'Cobain',
lastName: null,
};
console.log(user1.lastName!.toUpperCase()); // 에러! Cannot read properties of null (reading 'toUpperCase')
console.log(user1.lastName?.toUpperCase()); // undefined
변수 뒤에 느낌표 연산자 !
를 사용해서 값이 할당되어 있지 않은 변수나 객체를 사용할 수도 있다. 컴파일러에게 해당 변수의 값은 항상 할당되어 있다고(아직 값을 할당하지 않았어도) 알려주는 것이라고 보면 된다. 이를 Definite Assignment Assertions 라고 부른다.
일반적인 경우 값을 할당하지 않고 사용하면 아래처럼 TS2454 에러가 발생한다.
let num: number;
console.log(num) // 에러! TS2454: Variable 'num' is used before being assigned.
num
변수 뒤에 느낌표 !
를 붙이면 에러가 발생하지 않는다. 컴파일러에게 변수 num
은 항상 값이 할당되어 있다고 단언(assertion)했기 때문이다.
let num!: number;
console.log(num) // undefined