|
연산자를 사용하여 나타냅니다.function printId(id: number | string) {
console.log("Your ID is:", id);
}
// Ok, 'number' is assignable to parameter of type 'string | number'
printId(101);
// Ok, 'string' is assignable to parameter of type 'string | number'
printId("202");
// Error: Argument of type '{ myID: number}' is not assignable to parameter of type 'string | number'
printId({ myID: 1234});
boolean | number
= number | boolean
let thinker : string | null = null;
if (Math.random() > 0.5) {
// Ok, 'string' is assignable to type 'string | null'
thinker = "Susanne Langer";
}
let physicist = Math.random() > 0.5 ? "Marie Curie" : 85;
// Ok, Property 'toString' exist on type 'string | number'
physicist.toString();
// Error: Poperty 'toUpperCase' does not exist on type 'string | number'
// Property 'toUpperCase' does not exist on type 'number'
physicist.toUpperCase();
// Error: Poperty 'toFixed' does not exist on type 'string | number'
// Property 'toFixed' does not exist on type 'string'
physicist.toFixed();
let admiral: number | string;
// admiral : string
admiral = 'Grace Hooper';
// Error: Property 'toFixed' does not exist on type 'string'
admiral.toFixed();
// x : string | number
let x = Math.random() < 0.5 ? 10 : 'hello world';
x = 1;
// x : number
x.toFixed();
x = 'goodbye!';
// x : string
x.toUpperCase();
typeof operator
- JavaScript는
typeof
연산자를 사용하여 런타임에서 갖는 값의 타입에 대한 정보를 얻을 수 있습니다.typeof
연산자의 반환값
"string"
"number"
"bigint"
"boolean"
"symbol"
"undefined"
"object"
"function"
typeof
연산자의 반환값을 확인하는 것입니다.let researcher = Math.random() > 0.5 ? 'Rosalind Franklin' : 51;
if (typeof researcher === 'string') {
// researcher : string
researcher.toUpperCase();
}
!
를 사용한 논리적 부정과 else 문에서도 잘 작동합니다.if (!(typeof researcher === 'string')) {
// researcher : number
researcher.toFixed();
} else {
// researcher : string
researcher.toUpperCase();
}
typeof researcher === 'string'
? researcher.toUpperCase() // researcher : string
: researcher.toFixed(); // researcher : number
typeof null
typeof null === "object"
이기 때문에, typeof 연산자로 null
과 object
를 구분하지 못합니다.null
이 될 수 있다고 알려줍니다.function printAll(strs: string | string[] | null) {
if (typeof str === 'object') {
// strs : string[] | null
// Error: 'strs' is possibly 'null'
for (const s of strs) {
console.log(s);
}
} else if (typeof strs === 'string') {
// strs : string
console.log(strs);
} else {
// ...
}
}
truthy & falsy
- truthy
- JavaScript에서 boolean 문맥에서 true로 간주되는 값
- falsy로 정의된 값을 제외한 모든 값
- falsy
- JavaScript에서 boolean 문맥에서 false로 간주되는 값
0
,NaN
,""
,0n
,null
,undefined
&&
, ||
, if
조건문)을 사용하여 잠재적인 값 중 truthy로 확인된 일부에 한해서만 변수의 타입을 줄일 수 있습니다.null
이나 undefined
와 같은 값을 거르는데 자주 사용됩니다.let geneticist = Math.random() > 0.5 ? "Barbara McClintock" : undefined;
if (geneticist) {
// geneticist : string
geneticist.toUpperCase();
}
// geneticist : string | undefined
// Error: 'geneticist' is possibly 'undefined'
geneticist.toUpperCase();
string | false
의 값에 대해 알고 있는 것이 falsy라면, 그것이 빈 문자열인지 false인지 알 수 없습니다.let biologist = Math.random() > 0.5 && 'Rachel Carson';
if (biologist) {
// biologist : string
biologist;
} else {
// biologist : false | string
biologist;
}
!
를 사용하여 falsy 값을 필터링할 수 있습니다.function multiplyAll(
value: number[] | undefined,
factor: number
): number[] | undefined {
if (!values) {
// values : undefined
return values;
} else {
// values : number[]
return values.map((x) => x * factor);
}
}
equality operator
- strict equality operator (
===
,!==
)
- 같은 타입의 두 피연산자가 값이 일치하는지 비교합니다.
- 타입 변환을 시도하지 않습니다.
- equality operator (
==
,!=
)
- 두 피연산자의 타입의 다를 경우, 타입 변환하여 타입을 같게 만든 후 값이 일치하는지 비교합니다.
switch
문이나 ===
, !==
, ==
, !=
와 같은 equality checks를 통해 타입을 좁힙니다.function example(x: string | number, y: string | boolean) {
// the type of x has to be equal to the type of y
// common type between x and y is 'string'
if (x === y) {
// x : string
x.toUpperCase();
// y : string
y.toUpperCase();
} else {
// x : string | number
console.log(x);
// y : string | boolean
console.log(y);
}
}
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);
}
}
}
null == undefined
이기 때문에, ==
나 !=
를 이용해 값이 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
- JavaScript는
in
연산자를 사용하여 객체에 해당 이름의 속성이 존재하는지 확인할 수 있습니다.
in
연산자를 사용하여 잠재적인 타입들을 속성을 가진 타입으로 좁힐 수 있습니다."value" in union type
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();
}
in
연산자들을 사용하여 속성을 가진 타입으로 좁힐 때, 선택적 속성(optional property?
)를 가진 타입도 포함시킵니다.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 : Fish | Human
return animal.swim();
}
// animal : Bird | Human
return animal.fly();
}
instanceof operator
- JavaScript에서
A instanceof B
는 A가 B의 prototype chain에 존재하는지 확인합니다.
function logValue(x: Date | string) {
if (x instanceof Date) {
// x : Date
console.log(x.toUTCString());
} else {
// x : string
console.log(x.toUpperCase());
}
}
literal type
literal 타입 선언
// philosopher : 'Hypatia'
let philosopher : 'Hypatia'
// admiral : 'Grace Hooper'
const admiral = 'Grace Hooper';
primitive type
boolean
, null
, undefined
타입 외의 primitive 타입(string
, number
등)은 무한한 수의 literal 타입이 있습니다.
boolean
: true | falsenull
: null undefined
: undefinednumber
: 0 | 1 | 2 | ... | 0.1 | 0.2 | ...string
: '' | 'a' | 'b' | 'c' | ... | 'aa' | 'ab' | 'ac'let specificallyAda: 'Ada';
// specificallyAda : 'Ada'
specificallyAda = 'Ada';
// Error: type 'Bryon' is not assignable to type 'Ada'
specificallyAda = 'Bryon';
let specificallyAda: 'Ada' = 'Ada';
let str: string;
// Error: Type 'string' is not assignable to type '"Ada"'
specificallyAda = str;
let specificallyAda: 'Ada' = 'Ada';
let str: string;
// Ok
str = specificallyAda;
// union type with string literal types
function alignText(alignment: 'left' | 'right' | 'center') {
// ...
}
// Ok
alignText('left');
// Error: Argument of type 'down' is not assignable to parameter of type 'left' | 'right' | 'center'
alignText('down');
// union type with number literal types
function compare(a: string, b: string): -1 | 0 | 1 {
return a === b ? 0 : a > b : 1 : -1;
}
let lifespan: number | 'ongoing' | 'uncertain';
// lifespan : number
lifespan = 89;
// lifespan : 'ongoing'
lifespan = 'ongoing'
// Error: Type 'true' is not assignable to tyep 'number' | 'ongoing' | 'uncertain'
lifespan = true;
interface Options {
width: number;
}
function configure(x: Options | 'auto') {
// ...
}
configure({width: 100});
configure('auto');
// Error: Argument of type 'automatic' is not assignable to parameter of type Options | 'auto'
configure('automatic');
십억 달러의 실수(The Billion-Dollar Mistake)
- 다른 타입이 필요한 위치에서 null 값을 사용하도록 허용하는 타입 시스템
- 1965년, null 참조의 발명으로 수많은 오류, 취약성 및 시스템 충돌이 발생했으며, 지난 40년간 10억 달러의 피해를 입었을 것입니다(Tonny Hoare, 2009).
null
과 undefined
가 다르게 처리합니다.null
과 undefined
가 효과적으로 무시됩니다. null
이나 undefined
일 수 있는 값에 정상적으로 접근 가능합니다.null
이나 undefined
을 할당할 수 있습니다.// strictNullChecks : false
declare const loggedInUsername: string;
const users = [
{ name: 'Oby', age; 12 },
{ name: 'Heera', age; 32 },
]
const loggedInUser = users.find((u) => u.name === loggedInUsername);
console.log(loggedInUser.age);
let str: string;
str = null;
null
와 undefined
는 그 자신의 구별된 타입을 가지고 확인됩니다.null
이나 undefined
일 수 있는 값은 접근하기 전에 테스트를 해야합니다.null
이나 undefined
일 수 있는 값을 확인합니다.null
이나 undefined
을 할당할 수 없습니다.// strictNullChecks : true
declare const loggedInUsername: string;
const users = [
{ name: 'Oby', age; 12 },
{ name: 'Heera', age; 32 },
]
const loggedInUser = users.find((u) => u.name === loggedInUsername);
// Error: loggedInUser is possibly 'undefined'
console.log(loggedInUser.age);
let str: string;
// Error: Type 'null' is not assignable to type 'string'
str = null;
type 새로운 이름 = 타입
형태를 가집니다.// before
let rawDataFirst : boolean | number | string | null | undefined ;
let rawDataSecond : boolean | number | string | null | undefined ;
let rawDataThird : boolean | number | string | null | undefined ;
// after
type RawData = boolean | number | string | null | undefined ;
let rawDataFirst: RawData;
let rawDataSecond: RawData;
let rawDataThird: RawData;
// data.ts
type RawData = boolean | number | string | null | undefined ;
let rawDataFirst: RawData;
let rawDataSecond: RawData;
let rawDataThird: RawData;
// data.js(complied)
let rawDataFirst;
let rawDataSecond;
let rawDataThird;
type SomeType = string | undefined;
// Error: 'SomeType' only refer to a type, but is being used as a value here.
console.log(SomeType);
type Id = number | string;
// IdMabe : number | string | undefined | null
type IdMaybe = Id | undefined | null;
// Ok
type IdMaybe = Id | undefined | null;
type Id = number | string;