&
연산자를 사용하여 타입들을 결합한 타입type Colorful = {
color: string;
}
type Circle = {
radius: number;
}
type ColorfulCircle = Colorful & Circle;
function draw(circle: ColorfulCircle) {
console.log(`Color was ${circle.color}`);
console.log(`Radius was ${circle.radius}`);
}
// okay
draw({ color: "blue", radius: 42 });
// error
draw({ color: "red" });
interface Colorful {
color: string;
}
interface Circle {
radius: number;
}
interface ColorfulCircle extends Colorful, Circle {};
type Combinable = string | number;
type Numeric = number | boolean;
// Universal : number 타입
type Universal = Combinable & Numeric;
type Combinable = string | number;
type Numeric = string | number;
// Universal : string | number 타입
type Universal = Combinable & Numeric;
type Combinable = string | number;
type Numeric = null | boolean;
// Universal : never 타입
type Universal = Combinable & Numeric;
narrowing
이라고 함typeof
Type Guardstypeof
연산자는 해당 타입의 기본 정보를 반환함"string"
, "nunber"
, "bigint"
, "boolean"
, "undefined"
, "object"
, "function"
function printAll(strs: string | string[] | null) {
if (typeof strs === "object") {
// Error: Object is possibly 'null'
for (const s of strs) {
console.log(s);
}
} else if (typeof strs === "string") {
console.log(strs);
} else {
// do nothing
}
}
typof null
이 "object"
이므로 string[] | null
타입으로만 좁혀짐Boolean
함수나 !!
(doble-Boolean negation)을 사용하여 값을 boolean으로 바꿀 수 있음Boolean
함수를 사용한 경우, boolean 타입으로 추론됨!!
를 사용한 경우, narrow literal boolean 타입인 true
또는 false
로 추론됨Boolean("hello"); // type: boolean, value: true
!!"world"; // type: true, value: true
Boolean(""); // type: boolean, value: false
!!""; // type: false, value: false
null
이나 undefined
값을 거를 때 사용함function multiplyAll(
values: number[] | undefined,
factor: number
): number[] | undefined {
if (!values) {
return values;
} else {
return values.map((x) => x * factor);
}
}
switch
문과 equality operator ===
, !==
, ==
, !=
를 사용하여 타입을 좁힐 수 있음
strict equality operator(===
, !==
) : 두 값의 값과 타입이 같은지를 비교함
function example(x: string | number, y: string | boolean) {
if (x === y) {
// x, y : string
x.toUpperCase();
y.toLowerCase();
} else {
// x : string | number
console.log(x);
// y : string | boolean
console.log(y);
}
}
x===y가 true가 되려면, x와 y의 타입과 값이 같아야하므로, x와 y의 타입은 공통 타입인 string이 되어야함
특정한 literal 값이 아닌 경우에 대해서도 체크할 수 있음
function printAll(strs: string | string[] | null) {
if (strs !== null) {
// strs: string | string[]
if (typeof strs === "object") {
// strs: string[]
for (const s of strs) {
console.log(s);
}
} else if (typeof strs === "string") {
// strs: string
console.log(strs);
}
}
}
loose equality operator(==
, !=
) : 두 값을 비교할 때 암묵적 타입 변환을 통해 타입을 일치시킨 후 같은 값인지 비교함
undefined == null
이 true이므로 ==null
은 값이 null 또는 undefined인지를 확인함
interface Container {
value: number | null | undefined;
}
function multiplyValue(container: Container, factor: number) {
// Remove both 'null' and 'undefined' from the type.
if (container.value != null) {
// container.value : number
console.log(container.value);
container.value *= factor;
}
}
in
operator narrowingin
operator: 객체 안에 해당 이름의 속성이 존재하는지를 확인함type Fish = { swim: () => void };
type Bird = { fly: () => void };
function move(animal: Fish | Bird) {
if ("swim" in animal) {
// animal : Fish
return animal.swim();
}
// animal: Bird
return animal.fly();
}
type Fish = { swim: () => void };
type Bird = { fly: () => void };
type Human = { swim?: () => void; fly?: () => void };
function move(animal: Fish | Bird | Human) {
if ("swim" in animal) {
animal;
(parameter) animal: Fish | Human
} else {
animal;
(parameter) animal: Bird | Human
}
}
instanceof
narrowinginstanceof
B: A가 B의 인스턴스인지 확인함, A가 B의 프로토타입 체인에 존재하는지 확인함function logValue(x: Date | string) {
if (x instanceof Date) {
// x: Date
console.log(x.toUTCString());
} else {
// x: string
console.log(x.toUpperCase());
}
}
let x = Math.random() < 0.5 ? 10 : "hello world!";
// x: string | number
x = 1;
console.log(x);
// x: number;
x = "goodbye!";
console.log(x);
// x: string
let x = Math.random() < 0.5 ? 10 : "hello world!";
// x: string | number
x = true;
// Error: Type 'boolean' is not assignable to type 'string | number'
console.log(x);
interface Circle {
kind: "circle";
radius: number;
}
interface Square {
kind: "square";
sideLength: number;
}
type Shape = Circle | Square;
function getArea(shape: Shape) {
switch (shape.kind) {
case "circle":
// shape: Circle
return Math.PI * shape.radius ** 2;
case "square":
// shape: Square
return shape.sideLength ** 2;
}
}
never
타임은 모든 타입에 할당 가능하지만, never
타입에는 never
타입만 할당 가능함never
타입을 통해서 exhaustive 확인이 가능함type Shape = Circle | Square;
function getArea(shape: Shape) {
switch (shape.kind) {
case "circle":
return Math.PI * shape.radius ** 2;
case "square":
return shape.sideLength ** 2;
default:
// shape: never
const _exhaustiveCheck: never = shape;
return _exhaustiveCheck;
}
}
interface Triangle {
kind: "triangle";
sideLength: number;
}
type Shape = Circle | Square | Triangle;
function getArea(shape: Shape) {
switch (shape.kind) {
case "circle":
return Math.PI * shape.radius ** 2;
case "square":
return shape.sideLength ** 2;
default:
// Error: Type 'Triangle' is not assignable to type 'never'
const _exhaustiveCheck: never = shape;
return _exhaustiveCheck;
}
}