μ΅μ νμ μμ€ν μ λ΄λΆ μλ λ°©μμ νꡬν©λλ€. CFA(μ μ΄ νλ¦ λΆμ)κ° μ΄λ»κ² λ μμ νκ³ κ°λ ₯ν μ½λλ₯Ό μν κ°λ ₯ν νμ μ’νκΈ° κΈ°μ μ κ°λ₯νκ² νλμ§ μμ보μΈμ.
μ»΄νμΌλ¬λ μ΄λ»κ² λλν΄μ§λκ°: νμ μ’νκΈ°μ μ μ΄ νλ¦ λΆμ μ¬μΈ΅ νꡬ
κ°λ°μλ‘μ μ°λ¦¬λ λꡬμ μ‘°μ©ν μ§λ₯κ³Ό λμμμ΄ μνΈ μμ©ν©λλ€. μ½λλ₯Ό μμ±νλ©΄ IDEλ κ°μ²΄μμ μ¬μ©ν μ μλ λ©μλλ₯Ό μ¦μ μ μ μμ΅λλ€. λ³μλ₯Ό 리ν©ν°λ§νλ©΄ νμ κ²μ¬κΈ°κ° νμΌμ μ μ₯νκΈ°λ μ μ μ μ¬μ μΈ λ°νμ μ€λ₯λ₯Ό κ²½κ³ ν©λλ€. μ΄κ²μ λ§λ²μ΄ μλλλ€. μ κ΅ν μ μ λΆμμ κ²°κ³Όμ΄λ©°, κ°μ₯ κ°λ ₯νκ³ μ¬μ©μμκ² μΉμν κΈ°λ₯ μ€ νλκ° νμ μ’νκΈ°μ λλ€.
string λλ numberκ° λ μ μλ λ³μλ‘ μμ
ν΄ λ³Έ μ μ΄ μμ΅λκΉ? μμ
μ μννκΈ° μ μ ν΄λΉ μ νμ νμΈνκΈ° μν΄ if λ¬Έμ μμ±νμ κ²μ
λλ€. ν΄λΉ λΈλ‘ λ΄μμ μΈμ΄λ λ³μκ° stringμμ 'μκ³ ' λ¬Έμμ΄ κ΄λ ¨ λ©μλλ₯Ό μ κΈ ν΄μ νκ³ μλ₯Ό λ€μ΄ μ«μμ λν΄ .toUpperCase()λ₯Ό νΈμΆνλ €κ³ μλνλ κ²μ λ°©μ§νμ΅λλ€. νΉμ μ½λ κ²½λ‘ λ΄μμ μ νμ μ§λ₯μ μΌλ‘ κ°μ νλ κ²μ΄ νμ
μ’νκΈ°μ
λλ€.
κ·Έλ¬λ μ»΄νμΌλ¬λ νμ κ²μ¬κΈ°λ μ΄λ»κ² μ΄λ₯Ό λ¬μ±ν κΉμ? ν΅μ¬ λ©μ»€λμ¦μ μ μ΄ νλ¦ λΆμ(CFA)μ΄λΌκ³ νλ μ»΄νμΌλ¬ μ΄λ‘ μ κ°λ ₯ν κΈ°μ μ λλ€. μ΄ κΈ°μ¬μμλ μ΄ νλ‘μΈμ€μ λ§μ κ±·μ΄λΌ κ²μ λλ€. νμ μ’νκΈ°κ° λ¬΄μμΈμ§, μ μ΄ νλ¦ λΆμμ΄ μ΄λ»κ² μλνλμ§ μ΄ν΄λ³΄κ³ κ°λ μ ꡬνμ μλ΄ν©λλ€. μ΄ μ¬μΈ΅ νꡬλ νΈκΈ°μ¬ λ§μ κ°λ°μ, μ»΄νμΌλ¬ μμ§λμ΄λ₯Ό μ§λ§νλ μ¬λ λλ μ΅μ νλ‘κ·Έλλ° μΈμ΄λ₯Ό μμ νκ³ μμ°μ μΌλ‘ λ§λλ μ κ΅ν λ Όλ¦¬λ₯Ό μ΄ν΄νλ €λ λͺ¨λ μ¬λμ μν κ²μ λλ€.
νμ μ’νκΈ°λ 무μμ λκΉ? μ€μ©μ μΈ μκ°
ν΅μ¬μ μΌλ‘ νμ μ’νκΈ°(νμ κ°μ λλ νλ¦ νμ΄νμ΄λΌκ³ λ ν¨)λ μ μ νμ κ²μ¬κΈ°κ° νΉμ μ½λ μμ λ΄μμ μ μΈλ νμ λ³΄λ€ λ³μμ λν΄ λ ꡬ체μ μΈ νμ μ μΆλ‘ νλ νλ‘μΈμ€μ λλ€. μ λμ¨κ³Ό κ°μ κ΄λ²μν νμ μ κ°μ Έμ λ Όλ¦¬μ κ²μ¬ λ° ν λΉμ κΈ°λ°μΌλ‘ 'μ’νλλ€'.
TypeScriptμ λͺ νν ꡬ문μ μ¬μ©νμ¬ λͺ κ°μ§ μΌλ°μ μΈ μλ₯Ό μ΄ν΄λ³΄κ² μ΅λλ€. μ리λ Python(Mypy ν¬ν¨), Kotlin λ±κ³Ό κ°μ λ§μ μ΅μ μΈμ΄μ μ μ©λ©λλ€.
μΌλ°μ μΈ μ’νκΈ° κΈ°μ
-
`typeof` κ°λ: μ΄κ²μ κ°μ₯ κ³ μ μ μΈ μμ
λλ€. λ³μμ κΈ°λ³Έ μ νμ νμΈν©λλ€.
μ:
function processInput(input: string | number) {
if (typeof input === 'string') {
// μ΄ λΈλ‘ λ΄μμ 'input'μ λ¬Έμμ΄λ‘ μλ €μ Έ μμ΅λλ€.
console.log(input.toUpperCase()); // μ΄κ²μ μμ ν©λλ€!
} else {
// μ΄ λΈλ‘ λ΄μμ 'input'μ μ«μλ‘ μλ €μ Έ μμ΅λλ€.
console.log(input.toFixed(2)); // μ΄κ²λ μμ ν©λλ€!
}
} -
`instanceof` κ°λ: μμ±μ ν¨μ λλ ν΄λμ€λ₯Ό κΈ°λ°μΌλ‘ κ°μ²΄ νμ
μ μ’νλ λ° μ¬μ©λ©λλ€.
μ:
class User { constructor(public name: string) {} }
class Guest { constructor() {} }
function greet(person: User | Guest) {
if (person instanceof User) {
// 'person'μ User νμ μΌλ‘ μ’νμ§λλ€.
console.log(`Hello, ${person.name}!`);
} else {
// 'person'μ Guest νμ μΌλ‘ μ’νμ§λλ€.
console.log('Hello, guest!');
}
} -
Truthy 체ν¬: `null`, `undefined`, `0`, `false` λλ λΉ λ¬Έμμ΄μ νν°λ§νλ μΌλ°μ μΈ ν¨ν΄μ
λλ€.
μ:
function printName(name: string | null | undefined) {
if (name) {
// 'name'μ 'string | null | undefined'μμ 'string'μΌλ‘ μ’νμ§λλ€.
console.log(name.length);
}
} -
Equality λ° Property κ°λ: νΉμ 리ν°λ΄ κ° λλ μμ±μ μ‘΄μ¬ μ¬λΆλ₯Ό νμΈνλ©΄ νΉν νλ³λ μ λμ¨μ μ¬μ©νμ¬ νμ
μ μ’ν μλ μμ΅λλ€.
μ(νλ³λ μ λμ¨):
interface Circle { kind: 'circle'; radius: number; }
interface Square { kind: 'square'; sideLength: number; }
type Shape = Circle | Square;
function getArea(shape: Shape) {
if (shape.kind === 'circle') {
// 'shape'μ Circleλ‘ μ’νμ§λλ€.
return Math.PI * shape.radius ** 2;
} else {
// 'shape'μ Squareλ‘ μ’νμ§λλ€.
return shape.sideLength ** 2;
}
}
μ΄μ μ μμ²λ©λλ€. μ»΄νμΌ μκ° μμ μ±μ μ 곡νμ¬ κ΄λ²μν λ°νμ μ€λ₯λ₯Ό λ°©μ§ν©λλ€. λ λμ μλ μμ±μ ν΅ν΄ κ°λ°μ κ²½νμ κ°μ νκ³ μ½λλ₯Ό λ³΄λ€ μλͺ νκ² λ§λλλ€. λ¬Έμ λ νμ κ²μ¬κΈ°κ° μ΄ μν© μΈμμ μ΄λ»κ² ꡬμΆνλλλ κ²μ λλ€.
λ§λ²μ μμ§: μ μ΄ νλ¦ λΆμ(CFA) μ΄ν΄
μ μ΄ νλ¦ λΆμμ μ»΄νμΌλ¬ λλ νμ κ²μ¬κΈ°κ° νλ‘κ·Έλ¨μ΄ μ·¨ν μ μλ κ°λ₯ν μ€ν κ²½λ‘λ₯Ό μ΄ν΄ν μ μλλ‘ νλ μ μ λΆμ κΈ°μ μ λλ€. μ½λλ₯Ό μ€ννμ§ μκ³ κ΅¬μ‘°λ₯Ό λΆμν©λλ€. μ΄λ₯Ό μν΄ μ¬μ©λλ μ£Όμ λ°μ΄ν° ꡬ쑰λ μ μ΄ νλ¦ κ·Έλν(CFG)μ λλ€.
μ μ΄ νλ¦ κ·Έλν(CFG)λ 무μμ λκΉ?
CFGλ νλ‘κ·Έλ¨ μ€ν μ€μ ν΅κ³Όν μ μλ λͺ¨λ κ°λ₯ν κ²½λ‘λ₯Ό λνλ΄λ λ°©ν₯ κ·Έλνμ λλ€. λ€μκ³Ό κ°μ΄ ꡬμ±λ©λλ€.
- λ Έλ(λλ κΈ°λ³Έ λΈλ‘): μμκ³Ό λμ μ μΈνκ³ λ΄λΆ λλ μΈλΆλ‘ λΆκΈ°νμ§ μλ μ°μμ μΈ λͺ λ Ήλ¬Έ μνμ€μ λλ€. μ€νμ νμ λΈλ‘μ 첫 λ²μ§Έ λͺ λ Ήλ¬Έμμ μμνμ¬ μ€λ¨ λλ λΆκΈ° μμ΄ λ§μ§λ§ λͺ λ Ήλ¬ΈμΌλ‘ μ§νλ©λλ€.
- μμ§: μ΄λ μ μ΄ νλ¦ λλ κΈ°λ³Έ λΈλ‘ κ°μ 'μ ν'λ₯Ό λνλ λλ€. μλ₯Ό λ€μ΄ `if` λ¬Έμ 'μ°Έ' κ²½λ‘μ λν΄ νλ, 'κ±°μ§' κ²½λ‘μ λν΄ νλ, λ κ°μ λκ°λ μμ§κ° μλ λ Έλλ₯Ό λ§λλλ€.
κ°λ¨ν `if-else` λ¬Έμ λν CFGλ₯Ό μκ°νν΄ λ³΄κ² μ΅λλ€.
let x: string | number = ...;
if (typeof x === 'string') { // λΈλ‘ A (쑰건)
console.log(x.length); // λΈλ‘ B (μ°Έ λΆκΈ°)
} else {
console.log(x + 1); // λΈλ‘ C (κ±°μ§ λΆκΈ°)
}
console.log('Done'); // λΈλ‘ D (λ³ν© μ§μ )
κ°λ μ CFGλ λ€μκ³Ό κ°μ΅λλ€.
[ μ§μ μ ] --> [ λΈλ‘ A: `typeof x === 'string'` ] --> (μ°Έ μμ§) --> [ λΈλ‘ B ] --> [ λΈλ‘ D ]
\-> (κ±°μ§ μμ§) --> [ λΈλ‘ C ] --/
CFAλ μ΄ κ·Έλνλ₯Ό 'νμ'νκ³ κ° λ Έλμμ μ 보λ₯Ό μΆμ νλ κ²μ ν¬ν¨ν©λλ€. νμ μ’νκΈ°μ κ²½μ° μΆμ νλ μ 보λ κ° λ³μμ λν κ°λ₯ν νμ μ§ν©μ λλ€. μμ§μ 쑰건μ λΆμνμ¬ λΈλ‘μμ λΈλ‘μΌλ‘ μ΄λν λ μ΄ νμ μ 보λ₯Ό μ λ°μ΄νΈν μ μμ΅λλ€.
νμ μ’νκΈ°λ₯Ό μν μ μ΄ νλ¦ λΆμ ꡬν: κ°λ μ μ°μ΅
CFAλ₯Ό μ¬μ©νμ¬ μ’νκΈ°λ₯Ό μννλ νμ κ²μ¬κΈ°λ₯Ό ꡬμΆνλ νλ‘μΈμ€λ₯Ό λΆμν΄ λ³΄κ² μ΅λλ€. Rust λλ C++μ κ°μ μΈμ΄μ μ€μ ꡬνμ λ§€μ° λ³΅μ‘νμ§λ§ ν΅μ¬ κ°λ μ μ΄ν΄ν μ μμ΅λλ€.
1λ¨κ³: μ μ΄ νλ¦ κ·Έλν(CFG) ꡬμΆ
λͺ¨λ μ»΄νμΌλ¬μ 첫 λ²μ§Έ λ¨κ³λ μμ€ μ½λλ₯Ό μΆμ ꡬ문 νΈλ¦¬(AST)λ‘ νμ±νλ κ²μ λλ€. ASTλ μ½λμ ꡬ문 ꡬ쑰λ₯Ό λνλ λλ€. κ·Έλ° λ€μ μ΄ ASTμμ CFGκ° κ΅¬μ±λ©λλ€.
CFGλ₯Ό λΉλνλ μκ³ λ¦¬μ¦μ μΌλ°μ μΌλ‘ λ€μμ ν¬ν¨ν©λλ€.
- κΈ°λ³Έ λΈλ‘ 리λ μλ³: λͺ
λ Ήλ¬Έμ΄ λ€μκ³Ό κ°μ κ²½μ° λ¦¬λ(μ κΈ°λ³Έ λΈλ‘μ μμ)μ
λλ€.
- νλ‘κ·Έλ¨μ 첫 λ²μ§Έ λͺ λ Ήλ¬Έμ λλ€.
- λΆκΈ°μ λμμ λλ€(μ: `if` λλ `else` λΈλ‘ λ΄λΆμ μ½λ, 루νμ μμ).
- λΆκΈ° λλ λ°ν λͺ λ Ήλ¬Έ λ°λ‘ λ€μ λͺ λ Ήλ¬Έμ λλ€.
- λΈλ‘ ꡬμ±: κ° λ¦¬λμ λν΄ ν΄λΉ κΈ°λ³Έ λΈλ‘μ 리λ μ체μ λ€μ 리λλ₯Ό ν¬ν¨νμ§ μκ³ κ·Έ μ΄μ μ λͺ¨λ νμ λͺ λ Ήλ¬ΈμΌλ‘ ꡬμ±λ©λλ€.
- μμ§ μΆκ°: μμ§λ νλ¦μ λνλ΄κΈ° μν΄ λΈλ‘ μ¬μ΄μ κ·Έλ €μ§λλ€. `if (condition)`κ³Ό κ°μ 쑰건문μ 쑰건μ λΈλ‘μμ 'μ°Έ' λΈλ‘μΌλ‘μ μμ§μ 'κ±°μ§' λΈλ‘μΌλ‘μ μμ§(λλ `else`κ° μλ κ²½μ° λ°λ‘ λ€μ λΈλ‘)λ₯Ό λ§λλλ€.
2λ¨κ³: μν κ³΅κ° - νμ μ 보 μΆμ
λΆμκΈ°κ° CFGλ₯Ό ν΅κ³Όν λ κ° μ§μ μμ 'μν'λ₯Ό μ μ§ν΄μΌ ν©λλ€. νμ μ’νκΈ°μ κ²½μ° μ΄ μνλ κΈ°λ³Έμ μΌλ‘ λ²μ λ΄μ κ° λ³μλ₯Ό νμ¬ μ μ¬μ μΌλ‘ μ’νμ§ νμ κ³Ό μ°κ²°νλ λ§΅ λλ μ¬μ μ λλ€.
// μ½λμ μ£Όμ΄μ§ μ§μ μμμ κ°λ
μ μν
interface TypeState {
[variableName: string]: Type;
}
λΆμμ κ° λ³μκ° μ μΈλ νμ
μ κ°λ μ΄κΈ° μνλ‘ ν¨μ λλ νλ‘κ·Έλ¨μ μ§μ
μ μμ μμλ©λλ€. μ΄μ μμμ μ΄κΈ° μνλ { x: String | Number }μ
λλ€. κ·Έλ° λ€μ μ΄ μνλ κ·Έλνλ₯Ό ν΅ν΄ μ νλ©λλ€.
3λ¨κ³: μ‘°κ±΄λΆ κ°λ λΆμ(ν΅μ¬ λ Όλ¦¬)
μ¬κΈ°μ μ’νκΈ°κ° λ°μν©λλ€. λΆμκΈ°κ° μ‘°κ±΄λΆ λΆκΈ°(`if`, `while` λλ `switch` 쑰건)λ₯Ό λνλ΄λ λ Έλλ₯Ό λ§λλ©΄ 쑰건μ μ체μ μΌλ‘ κ²μ¬ν©λλ€. 쑰건μ λ°λΌ λ κ°μ λ€λ₯Έ μΆλ ₯ μν, μ¦ μ‘°κ±΄μ΄ μ°ΈμΈ κ²½λ‘μ λν μνμ μ‘°κ±΄μ΄ κ±°μ§μΈ κ²½λ‘μ λν μνλ₯Ό λ§λλλ€.
κ°λ typeof x === 'string'μ λΆμν΄ λ³΄κ² μ΅λλ€.
-
'μ°Έ' λΆκΈ°: λΆμκΈ°λ μ΄ ν¨ν΄μ μΈμν©λλ€. μ΄ ννμμ΄ μ°Έμ΄λ©΄ `x`μ νμ
μ `string`μ΄μ΄μΌ νλ€λ κ²μ μκ³ μμ΅λλ€. λ°λΌμ λ§΅μ μ
λ°μ΄νΈνμ¬ 'μ°Έ' κ²½λ‘μ λν μ μνλ₯Ό λ§λλλ€.
μ λ ₯ μν:
{ x: String | Number }μ°Έ κ²½λ‘μ λν μΆλ ₯ μν:
μ΄ μλ‘μ΄, λ μ νν μνλ μ°Έ λΆκΈ°(λΈλ‘ B)μ λ€μ λΈλ‘μΌλ‘ μ νλ©λλ€. λΈλ‘ B λ΄λΆμμ `x`μ λν λͺ¨λ μμ μ `String` νμ μ λν΄ κ²μ¬λ©λλ€.{ x: String } -
'κ±°μ§' λΆκΈ°: μ΄κ²λ μ€μν©λλ€.
typeof x === 'string'μ΄ κ±°μ§μ΄λ©΄ `x`μ λν΄ λ¬΄μμ μ μ μμκΉμ? λΆμκΈ°λ μλ νμ μμ 'μ°Έ' νμ μ λΊ μ μμ΅λλ€.μ λ ₯ μν:
{ x: String | Number }μ κ±°ν νμ :
Stringκ±°μ§ κ²½λ‘μ λν μΆλ ₯ μν:
μ΄ κ°μ λ μνλ 'κ±°μ§' κ²½λ‘λ₯Ό ν΅ν΄ λΈλ‘ Cλ‘ μ νλ©λλ€. λΈλ‘ C λ΄λΆμμ `x`λ μ¬λ°λ₯΄κ² `Number`λ‘ μ²λ¦¬λ©λλ€.{ x: Number }((String | Number) - String = Numberμ΄λ―λ‘)
λΆμκΈ°μλ λ€μν ν¨ν΄μ μ΄ν΄νλ κΈ°λ³Έ μ 곡 λ Όλ¦¬κ° μμ΄μΌ ν©λλ€.
x instanceof C: μ°Έ κ²½λ‘μμ `x`μ νμ μ `C`κ° λ©λλ€. κ±°μ§ κ²½λ‘μμλ μλ νμ μΌλ‘ μ μ§λ©λλ€.x != null: μ°Έ κ²½λ‘μμ `Null`κ³Ό `Undefined`λ `x`μ νμ μμ μ κ±°λ©λλ€.shape.kind === 'circle': `shape`κ° νλ³λ μ λμ¨μΈ κ²½μ° ν΄λΉ νμ μ `kind`κ° λ¦¬ν°λ΄ νμ `'circle'`μΈ λ©€λ²λ‘ μ’νμ§λλ€.
4λ¨κ³: μ μ΄ νλ¦ κ²½λ‘ λ³ν©
λΆκΈ°κ° λ€μ κ²°ν©λ λ, μ¦ `if-else` λ¬Έ λ€μ λΈλ‘ Dμμ μ΄λ»κ² λ©λκΉ? λΆμκΈ°λ μ΄ λ³ν© μ§μ μ λμ°©νλ λ κ°μ λ€λ₯Έ μνλ₯Ό κ°μ§λλ€.
- λΈλ‘ B(μ°Έ κ²½λ‘)μμ:
{ x: String } - λΈλ‘ C(κ±°μ§ κ²½λ‘)μμ:
{ x: Number }
λΈλ‘ Dμ μ½λλ μ΄λ€ κ²½λ‘λ₯Ό ννλμ§μ κ΄κ³μμ΄ μ ν¨ν΄μΌ ν©λλ€. μ΄λ₯Ό 보μ₯νκΈ° μν΄ λΆμκΈ°λ μ΄λ¬ν μνλ₯Ό λ³ν©ν΄μΌ ν©λλ€. κ° λ³μμ λν΄ λͺ¨λ κ°λ₯μ±μ ν¬κ΄νλ μ νμ μ κ³μ°ν©λλ€. μ΄λ μΌλ°μ μΌλ‘ λͺ¨λ λ€μ΄μ€λ κ²½λ‘μμ νμ μ μ λμ¨μ μ·¨νμ¬ μνλ©λλ€.
λΈλ‘ Dμ λν λ³ν©λ μν: { x: Union(String, Number) }λ { x: String | Number }λ‘ λ¨μνλ©λλ€.
νλ‘κ·Έλ¨μ μ΄ μμ μμ μ΄λ λΆκΈ°μμλ μ¬ μ μκΈ° λλ¬Έμ `x`μ νμ μ μλμ λ λμ νμ μΌλ‘ λλμκ°λλ€. μ΄κ²μ΄ `if-else` λΈλ‘ λ€μμ `x.toUpperCase()`λ₯Ό μ¬μ©ν μ μλ μ΄μ μ λλ€. νμ μμ 보μ₯μ΄ μ¬λΌμ‘κΈ° λλ¬Έμ λλ€.
5λ¨κ³: 루ν λ° ν λΉ μ²λ¦¬
-
ν λΉ: λ³μμ λν ν λΉμ CFAμ μ€μν μ΄λ²€νΈμ
λλ€. λΆμκΈ°κ°
x = 10;μ 보면 `x`μ λν΄ μ΄μ μ κ°μ‘λ λͺ¨λ μ’νκΈ° μ 보λ₯Ό λ²λ €μΌ ν©λλ€. μ΄μ `x`μ νμ μ ν λΉλ κ°μ νμ (μ΄ κ²½μ° `Number`)μΌλ‘ λͺ ννκ² μ μλ©λλ€. μ΄ λ¬΄ν¨νλ μ νμ±μ μν΄ λ§€μ° μ€μν©λλ€. κ°λ°μκ° νΌλνλ μΌλ°μ μΈ μμΈμ μ’νμ§ λ³μκ° ν΄λ‘μ λ΄λΆμμ μ¬ν λΉλμ΄ ν΄λ‘μ μΈλΆμμ μ’νκΈ°κ° λ¬΄ν¨νλλ κ²½μ°μ λλ€. - 루ν: 루νλ CFGμμ μ¬μ΄ν΄μ λ§λλλ€. 루ν λΆμμ λ 볡μ‘ν©λλ€. λΆμκΈ°λ 루ν λ³Έλ¬Έμ μ²λ¦¬ν λ€μ 루ν λμ μνκ° μμ μνμ μ΄λ€ μν₯μ λ―ΈμΉλμ§ νμΈν΄μΌ ν©λλ€. νμ μ λ³΄κ° μμ νλ λκΉμ§ 루ν λ³Έλ¬Έμ μ¬λ¬ λ² λ€μ λΆμν΄μΌ ν μλ μμ΅λλ€. μ΄λ₯Ό κ³ μ μ μ λλ¬νλ€κ³ ν©λλ€. μλ₯Ό λ€μ΄ `for...of` 루νμμ λ³μμ νμ μ 루ν λ΄μμ μ’νμ§ μ μμ§λ§ μ΄ μ’νκΈ°λ κ° λ°λ³΅λ§λ€ μ¬μ€μ λ©λλ€.
κΈ°λ³Έ μ¬ν κ·Έ μ΄μ: κ³ κΈ CFA κ°λ λ° κ³Όμ
μμ κ°λ¨ν λͺ¨λΈμ κΈ°λ³Έ μ¬νμ λ€λ£¨μ§λ§ μ€μ μλ리μ€μμλ μλΉν 볡μ‘μ±μ΄ λ°μν©λλ€.
νμ μ μ΄ λ° μ¬μ©μ μ μ νμ κ°λ
TypeScriptμ κ°μ μ΅μ μΈμ΄λ₯Ό μ¬μ©νλ©΄ κ°λ°μκ° CFA μμ€ν μ ννΈλ₯Ό μ€ μ μμ΅λλ€. μ¬μ©μ μ μ νμ κ°λλ λ°ν νμ μ΄ νΉμν νμ μ μ΄μΈ ν¨μμ λλ€.
function isUser(obj: any): obj is User {
return obj && typeof obj.name === 'string';
}
λ°ν νμ
obj is Userλ νμ
κ²μ¬κΈ°μκ² λ€μκ³Ό κ°μ΄ μλ €μ€λλ€. "μ΄ ν¨μκ° `true`λ₯Ό λ°ννλ©΄ μΈμ `obj`κ° `User` νμ
μ κ°λλ€κ³ κ°μ ν μ μμ΅λλ€."
CFAκ° if (isUser(someVar)) { ... }λ₯Ό λ§λλ©΄ ν¨μμ λ΄λΆ λ
Όλ¦¬λ₯Ό μ΄ν΄ν νμκ° μμ΅λλ€. μλͺ
μ μ λ’°ν©λλ€. 'μ°Έ' κ²½λ‘μμ someVarλ₯Ό `User`λ‘ μ’νλλ€. μ΄κ²μ μ ν리μΌμ΄μ
λλ©μΈμ νΉμ ν μλ‘μ΄ μ’νκΈ° ν¨ν΄μ λΆμκΈ°μκ² κ°λ₯΄μΉλ νμ₯ κ°λ₯ν λ°©λ²μ
λλ€.
ꡬ쑰 λΆν΄ λ° μ¨λ¦¬μ΄μ± λΆμ
λ³μμ λν 볡μ¬λ³Έμ΄λ μ°Έμ‘°λ₯Ό λ§λ€λ©΄ μ΄λ»κ² λ©λκΉ? CFAλ μ΄λ¬ν κ΄κ³λ₯Ό μΆμ ν λ§νΌ λλν΄μΌ ν©λλ€. μ΄λ₯Ό μ¨λ¦¬μ΄μ€ λΆμμ΄λΌκ³ ν©λλ€.
const { kind, radius } = shape; // shapeλ Circle | Square
if (kind === 'circle') {
// μ¬κΈ°μ 'kind'λ 'circle'λ‘ μ’νμ§λλ€.
// νμ§λ§ λΆμκΈ°κ° 'shape'κ° μ΄μ CircleμΈμ§ μκΉμ?
console.log(radius); // TSμμλ μ€ν¨ν©λλ€! 'radius'λ 'shape'μ μ‘΄μ¬νμ§ μμ μ μμ΅λλ€.
}
μμ μμμ λ‘컬 μμ `kind`λ₯Ό μ’νλ μλ `shape` κ°μ²΄κ° μλμΌλ‘ μ’νμ§μ§λ μμ΅λλ€. `shape`κ° λ€λ₯Έ κ³³μμ λ€μ ν λΉλ μ μκΈ° λλ¬Έμ λλ€. κ·Έλ¬λ μμ±μ μ§μ νμΈνλ©΄ μλν©λλ€.
if (shape.kind === 'circle') {
// μλν©λλ€! CFAλ 'shape' μμ²΄κ° νμΈλκ³ μμμ μκ³ μμ΅λλ€.
console.log(shape.radius);
}
μ κ΅ν CFAλ λ³μλΏλ§ μλλΌ λ³μμ μμ±λ μΆμ νκ³ μ¨λ¦¬μ΄μ€κ° 'μμ ν' μκΈ°λ₯Ό μ΄ν΄ν΄μΌ ν©λλ€(μ: μλ κ°μ²΄κ° `const`μ΄κ³ λ€μ ν λΉν μ μλ κ²½μ°).
ν΄λ‘μ λ° κ³ μ°¨ ν¨μμ μν₯
ν¨μκ° μΈμλ‘ μ λ¬λκ±°λ ν΄λ‘μ κ° λΆλͺ¨ λ²μμμ λ³μλ₯Ό μΊ‘μ²ν λ μ μ΄ νλ¦μ΄ λΉμ νμ΄ λκ³ λΆμνκΈ°κ° ν¨μ¬ λ μ΄λ €μμ§λλ€. λ€μμ κ³ λ €νμμμ€.
function process(value: string | null) {
if (value === null) {
return;
}
// μ΄ μμ μμ CFAλ 'value'κ° λ¬Έμμ΄μμ μκ³ μμ΅λλ€.
setTimeout(() => {
// μ½λ°± λ΄λΆμμ 'value'μ νμ
μ 무μμΌκΉμ?
console.log(value.toUpperCase()); // μ΄κ²μ μμ ν κΉμ?
}, 1000);
}
μ΄κ²μ μμ ν κΉμ? μν©μ λ°λΌ λ€λ¦ λλ€. νλ‘κ·Έλ¨μ λ€λ₯Έ λΆλΆμ΄ `setTimeout` νΈμΆκ³Ό μ€ν μ¬μ΄μ `value`λ₯Ό μμ ν κ°λ₯μ±μ΄ μλ κ²½μ° μ’νκΈ°λ μ ν¨νμ§ μμ΅λλ€. TypeScriptλ₯Ό ν¬ν¨ν λλΆλΆμ νμ κ²μ¬κΈ°λ μ¬κΈ°μ 보μμ μ λλ€. λ³κ²½ κ°λ₯ν ν΄λ‘μ μμ μΊ‘μ²λ λ³μλ λ³κ²½λ μ μλ€κ³ κ°μ νλ―λ‘ μΈλΆ λ²μμμ μνλ μ’νκΈ°λ λ³μκ° `const`κ° μλ ν μ½λ°± λ΄λΆμμ μ’ μ’ μμ€λ©λλ€.
`never`λ₯Ό μ¬μ©ν μμ μ± κ²μ¬
CFAμ κ°μ₯ κ°λ ₯ν μ ν리μΌμ΄μ μ€ νλλ μμ μ± κ²μ¬λ₯Ό νμ±ννλ κ²μ λλ€. `never` νμ μ λ°μν΄μλ μ λλ κ°μ λνλ λλ€. νλ³λ μ λμ¨μ λν `switch` λ¬Έμμ κ° μΌμ΄μ€λ₯Ό μ²λ¦¬ν λ CFAλ μ²λ¦¬λ μΌμ΄μ€λ₯Ό λΉΌμ λ³μμ νμ μ μ’νλλ€.
function getArea(shape: Shape) { // Shapeλ Circle | Square
switch (shape.kind) {
case 'circle':
// μ¬κΈ°μ shapeλ Circleμ
λλ€.
return Math.PI * shape.radius ** 2;
case 'square':
// μ¬κΈ°μ shapeλ Squareμ
λλ€.
return shape.sideLength ** 2;
default:
// μ¬κΈ°μ 'shape'μ νμ
μ 무μμΌκΉμ?
// (Circle | Square) - Circle - Square = neverμ
λλ€.
const _exhaustiveCheck: never = shape;
return _exhaustiveCheck;
}
}
λμ€μ `Triangle`μ `Shape` μ λμ¨μ μΆκ°νμ§λ§ ν΄λΉ `case`λ₯Ό μΆκ°νλ κ²μ μμ κ²½μ° `default` λΆκΈ°μ λλ¬ν μ μμ΅λλ€. ν΄λΉ λΆκΈ°μμ `shape`μ νμ μ `Triangle`μ΄ λ©λλ€. `Triangle`μ `never` νμ μ λ³μμ ν λΉνλ €κ³ νλ©΄ μ»΄νμΌ μκ° μ€λ₯κ° λ°μνμ¬ `switch` λ¬Έμ΄ λ μ΄μ μμ νμ§ μμμ μ¦μ μ립λλ€. μ΄κ²μ λΆμμ ν λ Όλ¦¬μ λν κ°λ ₯ν μμ λ§μ μ 곡νλ CFAμ λλ€.
κ°λ°μλ₯Ό μν μ€μ§μ μΈ μλ―Έ
CFAμ μ리λ₯Ό μ΄ν΄νλ©΄ λ³΄λ€ ν¨κ³Όμ μΈ νλ‘κ·Έλλ¨Έκ° λ μ μμ΅λλ€. μ¬λ°λ₯Ό λΏλ§ μλλΌ νμ κ²μ¬κΈ°μ 'μ μ΄μΈλ¦¬λ' μ½λλ₯Ό μμ±ν μ μμΌλ―λ‘ μ½λκ° λ λͺ νν΄μ§κ³ νμ κ΄λ ¨ λ¬Έμ κ° μ€μ΄λλλ€.
- μμΈ‘ κ°λ₯ν μ’νκΈ°λ₯Ό μν΄ `const`λ₯Ό μ νΈν©λλ€: λ³μλ₯Ό λ€μ ν λΉν μ μμΌλ©΄ λΆμκΈ°λ ν΄λΉ νμ μ λν΄ λ κ°λ ₯ν 보μ₯μ ν μ μμ΅λλ€. `let` λμ `const`λ₯Ό μ¬μ©νλ©΄ ν΄λ‘μ λ₯Ό ν¬ν¨ν λ 볡μ‘ν λ²μμμ μ’νκΈ°λ₯Ό μ μ§νλ λ° λμμ΄ λ©λλ€.
- νλ³λ μ λμ¨μ μμ©ν©λλ€: 리ν°λ΄ μμ±(`kind` λλ `type`κ³Ό κ°μ)μ μ¬μ©νμ¬ λ°μ΄ν° ꡬ쑰λ₯Ό μ€κ³νλ κ²μ CFA μμ€ν μ μλλ₯Ό μ리λ κ°μ₯ λͺ μμ μ΄κ³ κ°λ ₯ν λ°©λ²μ λλ€. μ΄λ¬ν μ λμ¨μ λν `switch` λ¬Έμ λͺ ννκ³ ν¨μ¨μ μ΄λ©° μμ μ± κ²μ¬λ₯Ό νμ©ν©λλ€.
- μ§μ κ²μ¬λ₯Ό μ μ§ν©λλ€: μ¨λ¦¬μ΄μ±μμ λ³Ό μ μλ―μ΄ κ°μ²΄μ μμ±μ μ§μ νμΈ(`obj.prop`)νλ κ²μ΄ μμ±μ λ‘컬 λ³μμ 볡μ¬νμ¬ νμΈνλ κ²λ³΄λ€ μ’νκΈ°μ λ μμ μ μ λλ€.
- CFAλ₯Ό μΌλμ λκ³ λλ²κΉ ν©λλ€: νμ μ μ’νμ΄μΌ νλ€κ³ μκ°λλ νμ μ€λ₯κ° λ°μνλ©΄ μ μ΄ νλ¦μ λν΄ μκ°ν΄ 보μΈμ. λ³μκ° μ΄λκ°μμ λ€μ ν λΉλμμ΅λκΉ? λΆμκΈ°κ° μμ ν μ΄ν΄ν μ μλ ν΄λ‘μ λ΄λΆμμ μ¬μ©λκ³ μμ΅λκΉ? μ΄ λ©ν λͺ¨λΈμ κ°λ ₯ν λλ²κΉ λꡬμ λλ€.
κ²°λ‘ : νμ μμ μ μ‘°μ©ν μνΈμ
νμ μ’νκΈ°λ μ§κ΄μ μ΄κ³ κ±°μ λ§λ²μ²λΌ λκ»΄μ§μ§λ§ μ μ΄ νλ¦ λΆμμ ν΅ν΄ μ€νλ μ»΄νμΌλ¬ μ΄λ‘ μ λν μμ λ κ°μ μ°κ΅¬μ μ°λ¬Όμ λλ€. νλ‘κ·Έλ¨μ μ€ν κ²½λ‘ κ·Έλνλ₯Ό μμ±νκ³ κ° μμ§μ λͺ¨λ λ³ν© μ§μ μμ νμ μ 보λ₯Ό κΌΌκΌΌνκ² μΆμ ν¨μΌλ‘μ¨ νμ κ²μ¬κΈ°λ λλΌμ΄ μμ€μ μ§λ₯κ³Ό μμ μ±μ μ 곡ν©λλ€.
CFAλ μ λμ¨ λ° μΈν°νμ΄μ€μ κ°μ μ μ°ν νμ μΌλ‘ μμ νλ©΄μλ νλ‘λμ μ λλ¬νκΈ° μ μ μ€λ₯λ₯Ό ν¬μ°©ν μ μλλ‘ νλ μ‘°μ©ν μνΈμμ λλ€. μ μ νμ΄νμ μ격ν μ μ½ μ‘°κ±΄ μ§ν©μμ λμ μ΄κ³ μν©μ μΈμνλ μ§μμΌλ‘ λ³νν©λλ€. λ€μμ νΈμ§κΈ°κ° `if` λΈλ‘ λ΄μμ μλ²½ν μλ μμ±μ μ 곡νκ±°λ `switch` λ¬Έμμ μ²λ¦¬λμ§ μμ μΌμ΄μ€λ₯Ό νλκ·Ένλ κ²½μ° λ§λ²μ΄ μλλΌ μ μ΄ νλ¦ λΆμμ μ°μνκ³ κ°λ ₯ν λ Όλ¦¬μμ μκ² λ κ²μ λλ€.