function padLeft(padding: number | string, input: string) {
if (typeof padding === "number") {
return " ".repeat(padding) + input;
}
return padding + input;
}
function printAll(strs: string | string[] | null) {
// 1. 배열은 자바스크립트에서 객체이기 때문에 object로 처리해야함
// 2. null도 객체이기 때문에 의도와 다르게 else문으로 가지 않음
if (typeof strs === "object") {
for (const s of strs) { //Object is possibly 'null'.
console.log(s);
}
} else if (typeof strs === "string") {
console.log(strs);
} else {
// do nothing
}
}
// 주의 - strs === "" 인 경우에 null과 같이 아무것도 하지 않음
function printAll(strs: string | string[] | null) {
if (strs) {
if (typeof strs === "object") {
for (const s of strs) {
console.log(s);
}
} else if (typeof strs === "string") {
console.log(strs);
}
}
}
// 올바른 타입 추론 방법
function printAll(strs: string | string[] | null) {
if (strs && typeof strs === "object") {
for (const s of strs) {
console.log(s);
}
} else if (typeof strs === "string") {
console.log(strs);
}
}
Boolean("hello"); // type: boolean, value: true
!!"world"; // type: true(범위가 더 좁아짐), value: true
function example(x: string | number, y: string | boolean) {
if (x === y) { //일치하는 타입은 string 뿐임으로 x, y는 string으로 처리됨
x.toUpperCase();
y.toLowerCase();
} else {
console.log(x); // string | number
console.log(y); // string | boolean
}
}
// printAll 함수 수정
function printAll(strs: string | string[] | null) {
if (strs !== null) {
if (typeof strs === "object") {
for (const s of strs) {
console.log(s);
}
} else if (typeof strs === "string") {
console.log(strs);
}
}
}
interface Container {
value: number | null | undefined;
}
function multiplyValue(container: Container, factor: number) {
// != 연산자를 사용해 !== 연산자를 두번 쓰지 않고 예외처리 가능
if (container.value != null) { //null과 undefined 동시에 제거
console.log(container.value);
container.value *= factor;
}
}
type Fish = { swim: () => void };
type Bird = { fly: () => void };
type Human = { swim?: () => void; fly?: () => void };
function move(animal: Fish | Bird | Human) {
if ("swim" in animal) {
// Fish | Human
} else {
// Bird | Human
}
}
function logValue(x: Date | string) {
if (x instanceof Date) {
console.log(x.toUTCString()); //Date
} else {
console.log(x.toUpperCase()); //string
}
}
let x = Math.random() < 0.5 ? 10 : "hello world!"; //string | number
x = 1; //number
console.log(x);
x = "bye" //string
console.log(x);
x = true; // Type 'boolean' is not assignable to type 'string | number'.
function padLeft(padding: number | string, input: string) {
if (typeof padding === "number") {
return " ".repeat(padding) + input;
}
// padding이 number인 경우는 이 부분에 도달 불가능
return padding + input; // padding: string
}
function example() {
let x: string | number | boolean;
x = Math.random() < 0.5;
console.log(x); //boolean
if (Math.random() < 0.5) {
x = "hello";
console.log(x); //string
} else {
x = 100;
console.log(x); //number
}
return x; //string | number
}
function isFish(pet: Fish | Bird): pet is Fish { //pet은 Fish로 간주
return Boolean((pet as Fish).swim);
}
let pet = getSmallPet();
if (isFish(pet)) {
pet.swim(); // Fish
} else {
pet.fly(); // Bird
}
// 배열을 좁힐때에도 사용 가능
const zoo: (Fish | Bird)[] = [getSmallPet(), getSmallPet(), getSmallPet()];
const underWater1: Fish[] = zoo.filter(isFish);
const underWater2: Fish[] = zoo.filter(isFish) as Fish[];
const underWater3: Fish[] = zoo.filter((pet): pet is Fish => {
if (pet.name === "sharkey") return false;
return isFish(pet);
});
interface Shape {
kind: "circle" | "square";
radius?: number;
sideLength?: number;
}
function getArea(shape: Shape) {
if (shape.kind === "circle") {
return Math.PI * shape.radius! ** 2;
}
else {
if (shape.sideLength?) return shape.sideLength? ** 2;
}
}
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":
return Math.PI * shape.radius ** 2;
case "square":
return shape.sideLength ** 2;
}
}
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:
const _exhaustiveCheck: never = shape; //Type 'Triangle' is not assignable to type 'never'.
return _exhaustiveCheck;
}
}
출처:
https://www.typescriptlang.org/docs/handbook/2/narrowing.html