π€ Chapter 10: μ λ€λ¦ νμ μ΄ν΄νκΈ°
π¦ μ λ€λ¦ νμ μ΄ν΄νκΈ°β
- μ λ€λ¦ νμ μ μΈν°νμ΄μ€λ ν΄λμ€, ν¨μ, νμ λ³μΉ λ±μ μ¬μ©ν μ μλ κΈ°λ₯μΌλ‘, ν΄λΉ μ¬λ²μ νμ μ 미리 μ§μ νμ§ μκ³ λ€μν νμ μ λμνλ €κ³ ν λ μ¬μ©νλ€.
// μ λ€λ¦ μΈν°νμ΄μ€ ꡬ문
interface IValuable<T> {
value: T;
}
// μ λ€λ¦ ν¨μ ꡬλΆ
function identity<T>(arg: T): T { return arg; }
// μ λ€λ¦ νμ
λ³μΉ ꡬ문
type IValuable<T> = {
value: T;
}
// μ λ€λ¦ ν΄λμ€ κ΅¬λ¬Έ
class Valuable<T> {
constructor(public value: T) {};
}
π μ λ€λ¦ μ¬μ©νκΈ°β
- μ λ€λ¦ μΈν°νμ΄μ€
IValuable<T>
λ₯Ό ꡬννλ μ λ€λ¦ ν΄λμ€λ μμ μ΄ κ°μ§ νμ λ³μT
λ₯Ό λ€μμ²λΌ μΈν°νμ΄μ€ μͺ½ μ λ€λ¦ νμ λ³μλ‘ λκΈΈ μ μλ€.
interface IValuable<T> {
value: T;
}
class Valuable<T> implements IValuable<T> {
constructor(public value: T) {}
}
// μ λ€λ¦ ν¨μλ λ€μμ²λΌ μμ μ νμ
λ³μ Tλ₯Ό μ λ€λ¦ μΈν°νμ΄μ€μ νμ
λ³μ μͺ½μΌλ‘ λκΈ°λ ννλ‘ κ΅¬νν μ μλ€.
const printValue = <T>(o: IValuable<T>): void => console.log(o.value);
printValue(new Valuable<number>(1)); // 1
printValue(new Valuable<boolean>(true)); // true
printValue(new Valuable<string>('hello')); // hello
printValue(new Valuable<number[]>([1, 2, 3])); // [1, 2, 3]
π¦ μ λ€λ¦ νμ μ μ½β
- μ λ€λ¦ νμ μ μ½μ νμ λ³μμ μ μ©ν μ μλ νμ μ λ²μλ₯Ό νμ νλ κΈ°λ₯μ νλ€.
- νμ μ€ν¬λ¦½νΈμμ μ λ€λ¦ ν¨μμ νμ μ μ ννκ³ μΆμ λλ λ€μ ꡬ문μ μ¬μ©νλ€.
<μ΅μ’
νμ
1 extend νμ
1, μ΅μ’
νμ
2 extend νμ
2>(a: μ΅μ’
νμ
1, b: μ΅μ’
νμ
2, ...) {}
printValueT
ν¨μλ μ λ€λ¦ νμ μ μ½ κ΅¬λ¬Έμ μ¬μ©ν΄ ꡬννκ³ μλ€.
const printValueT = <Q, T extends IValuable<Q>>(o: T) => console.log(o.value);
printValueT(new Valuable(1)); // 1
printValueT({ value: true }); //true
π new νμ μ μ½β
- νλ‘κ·Έλλ° λΆμΌμμ ν©ν 리 ν¨μλ
new
μ°μ°μλ₯Ό μ¬μ©ν΄ κ°μ²΄λ₯Ό μμ±νλ κΈ°λ₯μ νλ ν¨μλ₯Ό μλ―Ένλ€. - λ€μ μ½λμμ
create
ν¨μμ 맀κ°λ³μtype
μ μ€μ λ‘λ νμ μ΄λ€. λ°λΌμtype
λ³μμ νμ μ£ΌμμΌλ‘ λͺ μνT
λ νμ μ νμ μ ν΄λΉνλ€.
const create = <T>(type: T): T => new type();
- νμ§λ§ νμ μ€ν¬λ¦½νΈ μ»΄νμΌλ¬λλ νμ μ νμ μ νμ©νμ§ μμΌλ―λ‘ μ€λ₯ λ©μμ§κ° λ°μνλ€.
- κ·Έλμ λ€μκ³Ό κ°μ΄ μ¬μ©ν΄μ€ μ μλ€.
const create = <T extends { new(): T }>(type: T): T => new type();
// λ κ°κ²°ν λ¬Έλ²
const create = <T>(type: new() => T): T => new type();
- κ²°λ‘ μ μΌλ‘,
{ new(): T }
μnew() => T
λ κ°μ μλ―Έλ€.new
μ°μ°μλ₯Όtype
μ μ μ©νλ©΄μtype
μ μμ±μ μͺ½μΌλ‘ 맀κ°λ³μλ₯Ό μ λ¬ν΄μΌ ν λ λ€μμ²λΌnew(...args)
ꡬ문μ μ¬μ©νλ€.
const create = <T>(type: { new(...args): T }, ...args): T => new type(...args);
- λ€μ μ½λλ
Point
μ μΈμ€ν΄μ€λ₯Ό{ new(...args): T }
νμ μ μ½μ μ€μ νcreate
ν¨μλ‘ μμ±νλ μμ΄λ€.
class Point {
constructor(public x: number, public y: number) {};
}
[ create(Date), create(Point, 0, 0) ].forEach(s => console.log(s));
// 2020-05-22... Point { x: 0, y: 0 }
π μΈλ±μ€ νμ μ μ½β
- κ°μ²΄μ μΌμ μμ±λ€λ§ μΆλ €μ μ’ λ λ¨μν κ°μ²΄λ₯Ό λ§λ€μ΄μΌ ν λκ° μλ€.
const obj = {
name: 'Jane',
age: 22,
city: 'Seoul',
country: 'Korea',
}
const pick = (obj, keys) => keys.map(key => ({ [key]: obj[key] }))
.reduce((result, value) => ({ ...result, ...value }, {}))
// obj κ°μ²΄μμ nameκ³Ό age λ μμ±λ§ μΆμΆ
pick(obj, ['name', 'age']); // { name: 'Jane', age: 22 }
pick(obj, ['nam', 'agge']); // { name: undefined, age: undefined }
- μ μμ μ²λΌ μ€νκ° λ°μνλ©΄ μλ±ν κ²°κ³Όκ° λμ¨λ€. νμ
μ€ν¬λ¦½νΈλ μ΄λ¬ν μν©μ λ°©μ§ν λͺ©μ μΌλ‘ λ€μμ²λΌ
keyof T
ννλ‘ νμ μ μ½μ μ€μ ν μ μκ² μ§μνλ€. μ΄κ²μ μΈλ±μ€ νμ μ μ½μ΄λΌκ³ νλ€.
<T, K extends keyof T>
keyof T
ꡬ문μΌλ‘ νμK
κ° νμT
μ μμ± μ΄λ¦μ΄λΌκ³ νμ μ μ½μ μ€μ νλ€.
const pick = <T, K extends keyof T>(obj: T, keys: K[]) =>
keys.map(key => ({ [key]: obj[key] }))
.reduce((result, value) => ({ ...result, ...value }, {}))
- μ΄λ κ² νλ©΄ μ»΄νμΌμ ν΄λ³΄μ§λ μκ³ μμμ μλ‘ λ
nam
,agge
μ κ°μ μ λ ₯ μ€λ₯λ₯Ό μ½λ μμ± μμ μ νμ§ν μ μλ€.
π¦ λμ λ°μ΄ν° νμ β
- νμ μ€ν¬λ¦½νΈμμ λμ λ°μ΄ν° νμ μ ν©μ§ν© νμ κ³Ό κ΅μ§ν© νμ λ κ°μ§ μ’ λ₯κ° μλ€.
π ν©μ§ν© νμ β
- ν©μ§ν© νμ
μ *λλ(or)*μ μλ―ΈμΈ
|
κΈ°νΈλ‘ λ€μν νμ μ μ°κ²°ν΄μ λ§λ νμ μ λ§νλ€. - λ€μ μ½λμμ λ³μ
ns
μ νμ μΈNumberOrString
μnumber
λstring
νμ μ΄λ―λ‘, 1κ³Ό κ°μ μμhello
μ κ°μ λ¬Έμμ΄μ λͺ¨λ λ΄μ μ μλ€.
type NumberOrString = number | string;
let ns: NumberOrString = 1;
ns = 'hello';
π κ΅μ§ν© νμ β
- κ΅μ§ν© νμ
μ *μ΄κ³ (and)*μ μλ―ΈμΈ
&
κΈ°νΈλ‘ λ€μν νμ μ μ°κ²°ν΄μ λ§λ νμ μ λ§νλ€. - λνμ μΈ μλ‘ λ κ°μ κ°μ²΄λ₯Ό ν΅ν©ν΄μ μλ‘μ΄ κ°μ²΄λ₯Ό λ§λλ κ²μ΄λ€.
const mergeObjects = <T, U>(a: T, b: U): T & U => ({ ...a, ...b });
type INameable = { name: string };
type IAgeable = { age: number };
const nameAndAge: INameable & IAgeable = mergeObjects({ name: 'Jack' }, { age: 32 });
console.log(nameAndAge); // { name: 'Jack', age: 32 }
π μλ³ ν©μ§ν© ꡬ문β
- μλ³ ν©μ§ν¨ ꡬ문μ μ¬μ©νλ €λ©΄ ν©μ§ν© νμ μ ꡬμ±νλ μΈν°νμ΄μ€λ€μ΄ λͺ¨λ λκ°μ μ΄λ¦μ μμ±μ κ°μ§κ³ μμ΄μΌ νλ€.
- λ€μ μ½λμμ
ISquare
,IRectangle
,ICircle
μ λͺ¨λtag
λΌλ μ΄λ¦μ κ³΅ν΅ μμ±μ΄ μλ€.
interface ISquare { tag: 'square', size: number }
interface IRectangle { tag: 'rectangle', width: number, height: number }
interface ICircle { tag: 'circle', radius: number }
type IShape = ISquare | IRectangle | ICircle
const calcArea = (shape: IShape): number => {
switch(shape.tag) {
case 'square': return shape.size * shape.size;
case 'rectangle': return shape.width * shape.height;
case 'circle': return Math.PI * shape.radius * shape.radius;
}
return 0;
}
π¦ νμ κ°λβ
- λ€μ μ½λμμ
flyOrSwim
ν¨μλ 맀κ°λ³μo
κ°Bird
μ΄κ±°λFish
μ΄λ―λ‘ μ½λ μμ±μ΄ λͺ¨νΈν΄μ§ μ μλ€. - μ¦, ꡬ체μ μΌλ‘
Bird
μΈμ§Fish
μΈμ§ μμΌνλ€.
class Bird { fly() { console.log("I'm flying."); }}
class Fish { swim() { console.log("I'm swimming."); }}
const flyOrSwim = (o: Bird | Fish): void => {
// o.fly() ???
}
π νμ κ°λβ
- νμ
μ€ν¬λ¦½νΈμμ
instanceof
μ°μ°μλ μλ°μ€ν¬λ¦½νΈμ λ€λ₯΄κ² νμ κ°λ κ°λ₯μ΄ μλ€. - μ¬κΈ°μ νμ κ°λλ νμ μ λ³ννμ§ μμ μ½λ λλ¬Έμ νλ‘κ·Έλ¨μ΄ λΉμ μμ μΌλ‘ μ’ λ£λλ μν©μ 보νΈν΄μ€λ€λ μλ―Έλ€.
const flyOrSwim = (o: Bird | Fish): void => {
if (o instanceof Bird) {
o.fly();
} else if (o instanceof Fish) {
o.swim();
}
}
π is μ°μ°μλ₯Ό νμ©ν μ¬μ©μ μ μ νμ κ°λ ν¨μ μ μβ
- νμ
κ°λ κΈ°λ₯μ νλ ν¨μλ₯Ό ꡬνν μ μλ€. μ΄λ ν¨μμ λ°ν νμ
λΆλΆμ
is
λΌλ μ΄λ¦μ μ°μ°μλ₯Ό μ¬μ©ν΄μΌ νλ€.
const isFlyable = (o: Bird | Fish): o is Bird => {
return o instanceof Bird;
}
const isSWimmalbe = (o: Bird | Fish): o is Fish => {
return o instanceof Fish;
}
const swimOfFly = (o: Fish | Bird) => {
if (isSwimmable(o)) {
o.swim();
} else if (isFlyable(o)) {
o.fly();
}
}
[new Bird, new Fish].forEach(swimOfFly); // I'm flying. I'm swimming
π¦ F-λ°μ΄λ λ€νμ±β
π this νμ κ³Ό F-λ°μ΄λ λ€νμ±β
- νμ
μ€ν¬λ¦½νΈμμ
this
ν€μλλ νμ μΌλ‘λ μ¬μ©λλ€. this
κ° νμ μΌλ‘ μ¬μ©λλ©΄ κ°μ²΄μ§ν₯ μΈμ΄μμ μλ―Ένλ λ€νμ± ν¨κ³Όκ° λλλ°, μΌλ°μ μΈ λ€νμ±κ³Ό ꡬλΆνκΈ° μν΄this
νμ μΌλ‘ μΈν λ€νμ±μ F-λ°μ΄λ λ€νμ±μ΄λΌκ³ νλ€.
π F-λ°μ΄λ νμ β
- F-λ°μ΄λ νμ μ΄λ, μμ μ ꡬννκ±°λ μμνλ μλΈνμ μ ν¬ν¨νλ νμ μ λ§νλ€.
- λ€μ
IAddable<T>
λadd
λ©μλκ° λ΄κ° μλ λλ₯Ό μμνλ νμ μ λ°ννλ F-λ°μ΄λ νμ μ΄λ€.
interface IAddable<T> {
add(value: T): this
}
interface IMultiplyable<T> {
multiply(value: T): this
}
π IValueProvider<T>
μΈν°νμ΄μ€ ꡬνβ
- λ€μ
Calculator
ν΄λμ€λIValueProvider<T>
μΈν°νμ΄μ€λ₯Ό ꡬννκ³ μλ€. - μ΄ ν΄λμ€λ
_value
μμ±μprivate
μΌλ‘ λ§λ€μ΄Calculator
λ₯Ό μ¬μ©νλ μ½λμμ_value
μμ±μ΄ μλvalue()
λ©μλλ‘ μ κ·Όν μ μκ² μ€κ³λλ€.
import { IValueProvider } from '../interfaces';
export class Calculator implements IValueProvider<number> {
constructor(private _value: number = 0) {}
value(): number { return this._value };
}
- κ°μ λ°©μμΌλ‘ λ€μ
StringComposer
λνIValueProvider<T>
λ₯Ό ꡬννλ€.
import { IValueProvider } from '../interfaces';
export class StringComposer implements IValueProvider<string> {
constructor(private _value: string = '') {}
value(): string { return this._value };
}
π IAddable<T>
μ IMultiplyable<T>
μΈν°νμ΄μ€ ꡬνβ
Calculator
μadd
λ©μλλ ν΄λμ€μthis
κ°μ λ°ννλλ°, μ΄λ λ©μλ μ²΄μΈ κΈ°λ₯μ ꡬννκΈ° μν΄μμ΄λ€.
import { IValueProvider, IAddable } from '../interfaces';
export class Calculator implements IValueProvider<number>, IAddable<number> {
constructor(private _value: number = 0) {}
value(): number { return this._value };
add(value: number): this {
this._value = this._value + value;
return this;
}
}
IMultiplyable<T>
λ κ°μ λ°©λ²μΌλ‘Calculator
ν΄λμ€μ ꡬννλ€.
import { IValueProvider, IAddable, IMultiplyable } from '../interfaces';
export class Calculator implements IValueProvider<number>, IAddable<number>, IMultiplyable<number> {
constructor(private _value: number = 0) {}
value(): number { return this._value };
add(value: number): this {
this._value = this._value + value;
return this;
}
multiply(value: number): this {
this._value = this._value * value;
return this;
}
}
- λ€μμ
Calculator
ν΄λμ€λ₯Ό ν μ€νΈνλ μ½λμ΄λ€.
import { Calculator } from '../classes/Calculator';
const value = (new Calculator(1))
.add(2) // 3
.add(3) // 6
.multiply(4) // 24
.value()
console.log(value); // 24
StringComposer
λCalculator
λ₯Ό ꡬνν λ°©μμ κ·Έλλ‘ μ¬μ©ν΄ ꡬνν μ μλ€.
import { IValueProvider, IAddable, IMultiplyable } from '../interfaces';
export class StringComposer implements IValueProvider<string>, IAddable<string>, IMultiplyable<number> {
constructor(private _value: string = '') {}
value(): string { return this._value };
add(value: string): this {
this._value = this._value.concat(value);
return this;
}
multiply(repeat: number): this {
const value = this.value();
for (let index = 0; index < repeat; index++) {
this.add(value);
}
return this;
}
}
// StringComposer-test.ts
import { StringComposer } from '../classes/StringComposer';
const value = new StringComposer('hello')
.add(' ') // hello
.add('world') // hello world
.add('!') // hello world!
.multiply(3) // hello world!hello world!hello world!hello world!
.value();
console.log(value); // hello world!hello world!hello world!hello world!
- λ°ν νμ
this
λ μ΄λ€ λλCalculator
κ° λκΈ°λ νκ³ μ΄λ€ λλStringComposer
κ° λκΈ°λνλ€. - μ΄λ° λ°©μμΌλ‘ λμνλ κ²μ F-λ°μ΄λ λ€νμ±μ΄λΌκ³ νλ€.
π¦ nullable νμ κ³Ό νλ‘κ·Έλ¨ μμ μ±β
π nullable νμ μ΄λ?β
- μλ°μ€ν¬λ¦½νΈμ νμ
μ€ν¬λ¦½νΈλ
undefined
μ μ¬μ€μ κ°μ μλ―ΈμΈnull
μ΄ μλ€. νμ μ€ν¬λ¦½νΈμμλ μλ‘ νΈνλλ€. undefined
μnull
νμ μnullable
νμ μ΄λΌκ³ νλ©°, μ½λλ‘λ λ€μμ²λΌ ννν μ μλ€.
type nullable = undefined | null
const nullable: nullable = undefined;
- μ΄
nullable
νμ λ€μ νλ‘κ·Έλ¨μ΄ λμν λ νλ‘κ·Έλ¨μ λΉμ μμΌλ‘ μ’ λ£μν€λ μ£ΌμμμΈμ΄ λλ€. - μ¦, νλ‘κ·Έλ¨μ μμ μ±μ ν΄μΉλ€. ν¨μν μΈμ΄λ€μ μ΄λ₯Ό λ°©μ§νκΈ° μν΄ μ°μ°μλ ν΄λμ€λ₯Ό μ 곡νκΈ°λ νλ€.
π μ΅μ 체μ΄λ μ°μ°μβ
- λ³μκ° μ μΈλ§ λμμ λΏ μ΄λ€ κ°μΌλ‘ μ΄κΈ°νλμ§ μμΌλ©΄ μ½λλ₯Ό μμ±ν λλ λ¬Έμ κ° μμ§λ§, μ€μ λ‘ μ€ννλ©΄(λ°νμ) μ€λ₯κ° λ°μνλ©΄μ νλ‘κ·Έλ¨μ΄ λΉμ μμΌλ‘ μ’ λ£νλ€.
- μ΄λ° μ€λ₯λ μμ μ±μ ν΄μΉλ―λ‘ νλ‘κ·Έλλ° μΈμ΄ μ€κ³μλ€μ μ΅μ 체μ΄λ μ°μ°μμ λ λ³ν© μ°μ°μλ₯Ό μ 곡νλ€.
interface IPerson {
name: string
age?: number
}
let person: IPerson;
console.log(person?.name) // λ°νμ μ€λ₯ μμ΄ μ μμ μΌλ‘ μ€νλλ©°, undefinedκ°μ΄ λ°νλλ€.
π λ λ³ν© μ°μ°μβ
- λ€μ μ½λλ μ΅μ
체μ΄λ μ°μ°μμ λ λ³ν© μ°μ°μλ₯Ό νκΊΌλ²μ μ¬μ©νλλ°, μ΅μ
체μ΄λ μ°μ°μ λΆλΆμ΄
undefined
κ° λλ©΄ λ λ³ν© μ°μ°μκ° λμν΄undefined
λμ 0μ λ°ννλ€.
type ICoordinates = { longitude: number }
type ILocation = { country: string, coords: ICoordinates }
type IPerson = { name: string, location: ILocation }
let person: IPerson;
let longitude = person?.location?.coords?.longitude ?? 0;
console.log(longitude); // 0
π nullable νμ μ ν¨μν λ°©μ ꡬνβ
- νμ
μ€ν¬λ¦½νΈ μΈμ΄λ‘
Option
νμ μ ꡬνν΄λ³Έλ€. - λ€μ μ½λμμ
Option
ν΄λμ€λ μ€μΉΌλΌμμ μ¬μ©λλ λ°©μμΌλ‘ λμνλ€.
import { Some } from './Some';
import { None } from './None';
export class Option {
private constructor() {}
static Some<T>(value: T) { return new Some<T>(value); }
static None = new None();
}
export { Some, None };
Option
ν΄λμ€λ μμ±μκ°private
μΌλ‘ μ μΈλμμΌλ―λ‘,new
μ°μ°μλ‘Option
ν΄λμ€μ μΈμ€ν΄μ€λ₯Ό λ§λ€ μ μλ€.- μ¦,
Option
νμ κ°μ²΄λ λ€μμ²λΌOption.Some(κ°)
νΉμOption.None
ννλ‘λ§ μμ±ν μ μλ€. Some
κ³ΌNone
μ λ λ€IValuable<T>
μIFunctor<T>
λΌλ μΈν°νμ΄μ€λ₯Ό ꡬννκ³ μλλ°, λ ν΄λμ€λ κ°κΈ° λ€λ₯Έ μ΄ μΈν°νμ΄μ€λ₯Ό ꡬννλ€.IValuable
μ ꡬννλSome
κ³ΌNone
μ μ΄getOrElse
λ©μλλ₯Ό λ°λμ ꡬνν΄μΌ νλ€.
export interface IValuable<T> {
getOrElse(defaultValue: T)
}
- ν¨μν νλ‘κ·Έλλ° μΈμ΄μμλ
map
μ΄λΌλ λ©μλκ° μλ νμ λ€μ νν°λΌκ³ λΆλ₯Έλ€. λ€μμ νμ μ€ν¬λ¦½νΈ μΈμ΄λ‘ μ μΈν νν° μΈν°νμ΄μ€μ΄λ€.Some
κ³ΌNone
ν΄λμ€λIValuable
μ λ¬Όλ‘ μ΄IFunctor
μΈν°νμ΄μ€λ ꡬννκ³ μμΌλ―λ‘, μ΄ λ ν΄λμ€λgetOrElse
μmap
μ΄λΌλ μ΄λ¦μ λ©μλλ₯Ό μ 곡νλ€.
export interface IFunctor<T> {
map<U>(fn: (value: T) => U)
}
π Some ν΄λμ€ κ΅¬νβ
value
μμ±μprivate
μΌλ‘ μ μΈλμ΄ μμΌλ―λ‘Some
ν΄λμ€μ μ¬μ©μλ νμgetOrElse
λ©μλλ₯Ό ν΅ν΄Some
ν΄λμ€μ λ΄κΈ΄ κ°μ μ»μ΄μΌ νλ€. λνvalue
κ°μ λ³κ²½νλ €λ©΄ νμmap
λ©μλλ₯Ό μ¬μ©ν΄μΌλ§ νλ€.
import { IValuable } from './IValuable';
import { IFunctor } from './IFunctor';
export class Some<T> implements IValuable<T>, IFunctor<T> {
constructor(private value: T) {}
getOrElse(defaultValue: T) {
return this.value ?? defaultValue;
}
map<U>(fn: (T) => U) {
return new Some<U>(fn(this.value));
}
}
π None ν΄λμ€ κ΅¬νβ
- λ€μμ
None
ν΄λμ€μ ꡬν λ΄μ©μ΄λ€.
import { IValuable } from "./IValuable";
import { nullable } from "./nullable";
import { IFunctor } from './IFunctor';
export class None implements IValuable<nullable>, IFunctor<nullable> {
getOrElse<T>(defaultValue: T | nullable) {
return defaultValue;
}
map<U>(fn: (T) => U) {
return new None;
}
}
π Someκ³Ό None ν΄λμ€ μ¬μ©β
import { Option } from '../option/Option';
let m = Option.Some(1);
let value = m.map((value) => value + 1).getOrElse(1);
console.log(value); // 2
let n = Option.None;
value = n.map((value) => value + 1).getOrElse(0)
console.log(value); // 0
π Option νμ κ³Ό μμΈ μ²λ¦¬β
Option
νμ μ λΆμ ν¨κ³Όκ° μλ λΆμ ν¨μλ₯Ό μμ ν¨μλ‘ λ§λλ λ° ν¨κ³Όμ μ΄λ€.- λ€μ
parseNumber
ν¨μλparseInt
μ λ°νκ°μ΄NaN
μΈμ§μ λ°λΌOption.None
μ΄λOption.Some
νμ μ κ°μ λ°ννλ€.
import { IFunctor } from "./IFunctor";
import { IValuable } from "./IValuable";
import { Option } from "./Option";
export const perseNumber = (n: string): IFunctor<number> & IValuable<number> => {
const value = parseInt(n);
return isNaN(value) ? Option.None : Option.Some(value);
}
- λ€μ ν
μ€νΈ μ½λλ κ°μ± μ μμ μΌλ‘ λ³νλλ©΄
map
λ©μλκ° λμν΄ 4κ° μΆλ €λμ§λ§, κ°μ΄ λΉμ μμ μ΄λ©΄getOrElse(0)
κ° μ 곡νλ 0μ μΆλ ₯νλ€.
import { parseNumber } from '../option/parseNumber';
let value = parseNumber('1')
.map((value) => value + 1) // 2
.map((value) => value * 2) // 4
.getOrElse(0);
console.log(value);
value = parseNumber('hello world')
.map((value) => value + 1) // μ½λ°± ν¨μκ° νΈμΆλμ§ μλλ€
.map((value) => value * 2) // μ½λ°± ν¨μκ° νΈμΆλμ§ μλλ€
.getOrElse(0); // 0
console.log(value); // 0
- μλ°μ€ν¬λ¦½νΈμ
JSON.parse
ν¨μλ 맀κ°λ³μκ° μ μμ μΈ JSON ν¬λ§· λ¬Έμμ΄μ΄ μλλ©΄ μμΈλ₯Ό λ°μμν¨λ€. - μμΈλ₯Ό λ°μμν€λ ν¨μλ λΆμ ν¨κ³Όκ° μλ λΆμ ν¨μμ΄μ§λ§, λ€μ
parseJson
ν¨μλtry/catch
ꡬ문과Option
μ νμ©ν΄ μμ ν¨μκ° λμλ€.
import { IValuable } from './IValuable';
import { IFunctor } from './IFunctor';
import { Option } from './Option';
export const parseJson = <T>(json: string): IValuable<T> & IFunctor<T> => {
try {
const value = JSON.parse(json);
return Option.Some<T>(value);
} catch (error) {
return Option.None;
}
}
- λ€μ ν μ€νΈ μ½λλ λΉμ μμ μΌλ‘ μ’ λ£νμ§ μκ³ μ μμ μΌλ‘ λμνλ€.
import { parseJson } from '../option/parseJson';
const json = JSON.stringify({
name: 'Jack',
age: 32,
});
let value = parseJson(json).getOrElse({});
console.log(value); // { name: 'Jack', age: 32 }
value = parseJson('hello world').getOrElse({});
console.log(value); // {}