Typescript: ์ œ์•ˆ: get/set ์ ‘๊ทผ์ž๋ฅผ ๋‹ค๋ฅธ ์œ ํ˜•์œผ๋กœ ํ—ˆ์šฉ

์— ๋งŒ๋“  2015๋…„ 03์›” 26์ผ  ยท  125์ฝ”๋ฉ˜ํŠธ  ยท  ์ถœ์ฒ˜: microsoft/TypeScript

get/set ์ ‘๊ทผ์ž๊ฐ€ ๋™์ผํ•œ ์œ ํ˜•์„ ๊ฐ–๋„๋ก ์š”๊ตฌํ•˜๋Š” ํ˜„์žฌ ์ œ์•ฝ์„ ์™„ํ™”ํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ์žˆ๋‹ค๋ฉด ์ข‹์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ƒํ™ฉ์—์„œ ๋„์›€์ด ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

class MyClass {

    private _myDate: moment.Moment;

    get myDate(): moment.Moment {
        return this._myDate;
    }

    set myDate(value: Date | moment.Moment) {
        this._myDate = moment(value);
    }
}

ํ˜„์žฌ ์ด๊ฒƒ์€ ๋ถˆ๊ฐ€๋Šฅํ•œ ๊ฒƒ ๊ฐ™์œผ๋ฉฐ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

class MyClass {

    private _myDate: moment.Moment;

    get myDate(): moment.Moment {
        return this._myDate;
    }

    set myDate(value: moment.Moment) {
        assert.fail('Setter for myDate is not available. Please use: setMyDate() instead');
    }

    setMyDate(value: Date | moment.Moment) {
        this._myDate = moment(value);
    }
}

์ด๊ฒƒ์€ ์ด์ƒ์ ์ด์ง€ ์•Š์œผ๋ฉฐ ๋‹ค๋ฅธ ์œ ํ˜•์ด ํ—ˆ์šฉ๋œ๋‹ค๋ฉด ์ฝ”๋“œ๊ฐ€ ํ›จ์”ฌ ๊นจ๋—ํ•ด์งˆ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๊ฐ์‚ฌ ํ•ด์š”!

Design Limitation Suggestion Too Complex

๊ฐ€์žฅ ์œ ์šฉํ•œ ๋Œ“๊ธ€

๋‹ค๋ฅธ ์œ ํ˜•์˜ JavaScript getter ๋ฐ setter๋Š” ์™„๋ฒฝํ•˜๊ฒŒ ์œ ํšจํ•˜๊ณ  ํ›Œ๋ฅญํ•˜๊ฒŒ ์ž‘๋™ํ•˜๋ฉฐ ์ด๊ฒƒ์ด ์ด ๊ธฐ๋Šฅ์˜ ์ฃผ์š” ์ด์ /๋ชฉ์ ์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. TypeScript๋ฅผ ๊ธฐ์˜๊ฒŒ ํ•˜๊ธฐ ์œ„ํ•ด setMyDate() ๋ฅผ ์ œ๊ณตํ•ด์•ผ ํ•˜๋Š” ๊ฒƒ์€ ๊ทธ๊ฒƒ์„ ๋ง์นฉ๋‹ˆ๋‹ค.

๋‹ค์Œ ํŒจํ„ด์„ ๋”ฐ๋ฅด๋Š” ์ˆœ์ˆ˜ JS ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์— ๋Œ€ํ•ด์„œ๋„ ์ƒ๊ฐํ•ด ๋ณด์‹ญ์‹œ์˜ค. .d.ts๋Š” ๊ณต์šฉ์ฒด ๋˜๋Š” any ๋ฅผ ๋…ธ์ถœํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๋ฌธ์ œ๋Š” ์ ‘๊ทผ์ž๊ฐ€ ์ผ๋ฐ˜ ์†์„ฑ๊ณผ ๋‹ค๋ฅด๊ฒŒ .d.ts์— ํ‘œ์‹œ๋˜์ง€ ์•Š๋Š”๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๊ทธ๋Ÿฐ ๋‹ค์Œ ์ด ์ œํ•œ์ด ์ˆ˜์ •๋˜๊ณ  ์ด ๋ฌธ์ œ๊ฐ€ ๊ณ„์† ์—ด๋ ค ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

// MyClass.d.ts

// Instead of generating:
declare class MyClass {
  myDate: moment.Moment;
}

// Should generate:
declare class MyClass {
  get myDate(): moment.Moment;
  set myDate(value: Date | moment.Moment);
}

// Or shorter syntax:
declare class MyClass {
  myDate: (get: moment.Moment, set: Date | moment.Moment);
  // and 'fooBar: string' being a shorthand for 'fooBar: (get: string, set: string)'
}

๋ชจ๋“  125 ๋Œ“๊ธ€

์—ฌ๊ธฐ์—์„œ ์ด๊ฒƒ์ด ์–ผ๋งˆ๋‚˜ ์ข‹์€์ง€ ์•Œ ์ˆ˜ ์žˆ์ง€๋งŒ(์ง€๊ธˆ์€ ๋ฌธ์ œ๋ฅผ ์ฐพ์„ ์ˆ˜๋Š” ์—†์ง€๋งŒ ์ด์ „์— ์š”์ฒญํ•œ ์ ์ด ์žˆ์Œ) ์œ ํ‹ธ๋ฆฌํ‹ฐ๊ฐ€ ์ด๋ฅผ ๋ณด์ฆํ•˜๊ธฐ์— ์ถฉ๋ถ„ํ•œ์ง€ ์—ฌ๋ถ€๋Š” ๋ถˆ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. ๋ฌธ์ œ๋Š” ์ ‘๊ทผ์ž๊ฐ€ .d.ts์—์„œ ์ผ๋ฐ˜ ์†์„ฑ๊ณผ ๋‹ค๋ฅด๊ฒŒ ํ‘œ์‹œ๋˜์ง€ ์•Š๋Š”๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ ๊ด€์ ์—์„œ ๋ณด๋ฉด ๋™์ผํ•˜๊ฒŒ ๋ณด์ด๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. getter์™€ setter ์‚ฌ์ด์— ์ฐจ์ด๊ฐ€ ์—†๋‹ค๋Š” ์˜๋ฏธ์ด๋ฏ€๋กœ a) ๊ตฌํ˜„์ด ๋‹จ์ผ ์ธ์Šคํ„ด์Šค ๋ฉค๋ฒ„๊ฐ€ ์•„๋‹Œ ์ ‘๊ทผ์ž๋ฅผ ์‚ฌ์šฉํ•˜๋„๋ก ์š”๊ตฌํ•˜๊ณ  b) getter์™€ setter ๊ฐ„์˜ ์œ ํ˜• ์ฐจ์ด๋ฅผ ์ง€์ •ํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ์—†์Šต๋‹ˆ๋‹ค.

๋น ๋ฅธ ๋‹ต๋ณ€ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค, Dan. ๋œ ์šฐ์•„ํ•œ ๋ฐฉ๋ฒ•์„ ๋”ฐ๋ฅด๊ฒ ์Šต๋‹ˆ๋‹ค. ํ›Œ๋ฅญํ•œ ์ž‘์—…์— ๊ฐ์‚ฌ๋“œ๋ฆฝ๋‹ˆ๋‹ค!

๋‹ค๋ฅธ ์œ ํ˜•์˜ JavaScript getter ๋ฐ setter๋Š” ์™„๋ฒฝํ•˜๊ฒŒ ์œ ํšจํ•˜๊ณ  ํ›Œ๋ฅญํ•˜๊ฒŒ ์ž‘๋™ํ•˜๋ฉฐ ์ด๊ฒƒ์ด ์ด ๊ธฐ๋Šฅ์˜ ์ฃผ์š” ์ด์ /๋ชฉ์ ์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. TypeScript๋ฅผ ๊ธฐ์˜๊ฒŒ ํ•˜๊ธฐ ์œ„ํ•ด setMyDate() ๋ฅผ ์ œ๊ณตํ•ด์•ผ ํ•˜๋Š” ๊ฒƒ์€ ๊ทธ๊ฒƒ์„ ๋ง์นฉ๋‹ˆ๋‹ค.

๋‹ค์Œ ํŒจํ„ด์„ ๋”ฐ๋ฅด๋Š” ์ˆœ์ˆ˜ JS ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์— ๋Œ€ํ•ด์„œ๋„ ์ƒ๊ฐํ•ด ๋ณด์‹ญ์‹œ์˜ค. .d.ts๋Š” ๊ณต์šฉ์ฒด ๋˜๋Š” any ๋ฅผ ๋…ธ์ถœํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๋ฌธ์ œ๋Š” ์ ‘๊ทผ์ž๊ฐ€ ์ผ๋ฐ˜ ์†์„ฑ๊ณผ ๋‹ค๋ฅด๊ฒŒ .d.ts์— ํ‘œ์‹œ๋˜์ง€ ์•Š๋Š”๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๊ทธ๋Ÿฐ ๋‹ค์Œ ์ด ์ œํ•œ์ด ์ˆ˜์ •๋˜๊ณ  ์ด ๋ฌธ์ œ๊ฐ€ ๊ณ„์† ์—ด๋ ค ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

// MyClass.d.ts

// Instead of generating:
declare class MyClass {
  myDate: moment.Moment;
}

// Should generate:
declare class MyClass {
  get myDate(): moment.Moment;
  set myDate(value: Date | moment.Moment);
}

// Or shorter syntax:
declare class MyClass {
  myDate: (get: moment.Moment, set: Date | moment.Moment);
  // and 'fooBar: string' being a shorthand for 'fooBar: (get: string, set: string)'
}

๋‚˜๋Š” ์ด๊ฒƒ์ด ๋‹จ์ง€ ์˜๊ฒฌ์ด๋ผ๋Š” ๊ฒƒ์„ ์•Œ๊ณ  ์žˆ์ง€๋งŒ $ a.x = y; $#$ ์งํ›„์— a.x === y ๊ฐ€ true $๊ฐ€ ์•„๋‹Œ ๊ฒƒ๊ณผ ๊ฐ™์€ setter๋ฅผ ์ž‘์„ฑํ•˜๋Š” ๊ฒƒ์€ ๊ฑฐ๋Œ€ํ•œ ์œ„ํ—˜ ์‹ ํ˜ธ์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ์†Œ๋น„์ž๋Š” ์–ด๋–ค ์†์„ฑ์— ๋งˆ๋ฒ•์˜ ๋ถ€์ž‘์šฉ์ด ์žˆ๊ณ  ์–ด๋–ค ์†์„ฑ์ด ์—†๋Š”์ง€ ์–ด๋–ป๊ฒŒ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?

๋งˆ๋ฒ• ๋ถ€์ž‘์šฉ์ด ์žˆ๋Š” ์†์„ฑ๊ณผ ๊ทธ๋ ‡์ง€ ์•Š์€ ์†์„ฑ์„ ์–ด๋–ป๊ฒŒ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?

JavaScript์—์„œ๋Š” ์ง๊ด€์ ์ด์ง€ ์•Š์„ ์ˆ˜ ์žˆ์œผ๋ฉฐ TypeScript์—์„œ๋Š” ๋„๊ตฌ(IDE + ์ปดํŒŒ์ผ๋Ÿฌ)๊ฐ€ ๋ถˆํ‰ํ•ฉ๋‹ˆ๋‹ค. TypeScript๋ฅผ ๋‹ค์‹œ ์ข‹์•„ํ•˜๋Š” ์ด์œ ๋Š” ๋ฌด์—‡์ž…๋‹ˆ๊นŒ? :)

๋‹ค๋ฅธ ์œ ํ˜•์˜ JavaScript getter ๋ฐ setter๋Š” ์™„๋ฒฝํ•˜๊ฒŒ ์œ ํšจํ•˜๊ณ  ํ›Œ๋ฅญํ•˜๊ฒŒ ์ž‘๋™ํ•˜๋ฉฐ ์ด๊ฒƒ์ด ์ด ๊ธฐ๋Šฅ์˜ ์ฃผ์š” ์ด์ /๋ชฉ์ ์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

์ด๊ฒƒ์€ JavaScript๊ฐ€ ์•ฝํ•˜๊ฒŒ ํ˜•์‹ํ™”๋˜์–ด ์žˆ์œผ๋ฏ€๋กœ TypeScript๊ฐ€ ์•ฝํ•˜๊ฒŒ ํ˜•์‹ํ™”๋˜์–ด์•ผ ํ•œ๋‹ค๋Š” ์ฃผ์žฅ์ž…๋‹ˆ๋‹ค. :-์—์Šค

์ด๊ฒƒ์€ JavaScript๊ฐ€ ์•ฝํ•˜๊ฒŒ ํ˜•์‹ํ™”๋˜์–ด ์žˆ์œผ๋ฏ€๋กœ TypeScript๊ฐ€ ์•ฝํ•˜๊ฒŒ ํ˜•์‹ํ™”๋˜์–ด์•ผ ํ•œ๋‹ค๊ณ  ์ฃผ์žฅํ•ฉ๋‹ˆ๋‹ค.

C#์€ ์ด๋ฅผ ํ—ˆ์šฉํ•˜๋ฉฐ ์ด ์–ธ์–ด๋ฅผ ์•ฝํ•˜๊ฒŒ ํ˜•์‹ํ™” ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. C#์€ ๋‹ค๋ฅธ ํ˜•์‹์˜ get/set์„ ํ—ˆ์šฉํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

C#์€ ์ด๋ฅผ ํ—ˆ์šฉํ•˜๋ฉฐ ์ด ์–ธ์–ด๋ฅผ ์•ฝํ•˜๊ฒŒ ํ˜•์‹ํ™” ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. C#์€ ๋‹ค๋ฅธ ํ˜•์‹์˜ get/set์„ ํ—ˆ์šฉํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

:๋ˆˆ์ง“:

์ ‘๊ทผ์ž๊ฐ€ ์•ฝํ•œ ์œ ํ˜•์ด์–ด์•ผ ํ•œ๋‹ค๊ณ  ์ฃผ์žฅํ•˜๋Š” ์‚ฌ๋žŒ์€ ์•„๋ฌด๋„ ์—†์œผ๋ฉฐ ์œ ํ˜•์„ ์ •์˜ํ•  ์ˆ˜ ์žˆ๋Š” ์œ ์—ฐ์„ฑ์ด ์žˆ์–ด์•ผ ํ•œ๋‹ค๊ณ  ์ฃผ์žฅํ•ฉ๋‹ˆ๋‹ค.

๋ณดํ†ต ์˜ค๋ž˜๋œ ๊ฐœ์ฒด๋ฅผ ๊ฐœ์ฒด ์ธ์Šคํ„ด์Šค์— ๋ณต์‚ฌํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์Šต๋‹ˆ๋‹ค.

    get fields(): Field[] {
      return this._fields;
    }

    set fields(value: any[]) {
      this._fields = value.map(Field.fromJson);
    }

๊ทธ๊ฒƒ์€ ๋Œ€์•ˆ๋ณด๋‹ค ํ›จ์”ฌ ์ข‹์œผ๋ฉฐ ๋‚ด setter๊ฐ€ ์ •ํ™•ํ•œ ์œ ํ˜•์˜ ๋…ผ๋ฆฌ setter๋ฅผ ์บก์Šํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

@paulwalker ๊ฑฐ๊ธฐ์—์„œ ์‚ฌ์šฉํ•˜๋Š” ํŒจํ„ด( any ์„ ๋ฐ›๋Š” setter์™€ ๋” ๊ตฌ์ฒด์ ์ธ ์œ ํ˜•์„ ๋ฐ˜ํ™˜ํ•˜๋Š” getter)์€ ์˜ค๋Š˜ ์œ ํšจํ•ฉ๋‹ˆ๋‹ค.

@danquirk ๋ฐ˜๊ฐ‘ ์Šต๋‹ˆ๋‹ค, ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค! ST์šฉ IDE ํ”Œ๋Ÿฌ๊ทธ์ธ ์ปดํŒŒ์ผ๋Ÿฌ๋ฅผ ์—…๋ฐ์ดํŠธํ•ด์•ผ ํ•˜๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

@danquirk ๋†€์ดํ„ฐ(๋˜๋Š” ๋ฒ„์ „ 1.6.2)์— ๋”ฐ๋ผ ์ž‘๋™ํ•˜์ง€ ์•Š๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.
http://www.typescriptlang.org/Playground#src =%0A%0Aclass%20Foo%20%7B%0A%0A%20%20get%20items()%3A%20string%5B%5D%20%7B%0A %09%20%20๋ฐ˜ํ™˜%20%5B%5D%3B%0A%20%20%7D%0A%20%20%0A%20%20set%20items(value%3A%20any)%20%7B%0A% 09%20%20%0A%20%20%7D%0A%7D

๋ฐฉ๊ธˆ typescript@next (๋ฒ„์ „ 1.8.0-dev.20151102)๋กœ ํ…Œ์ŠคํŠธํ–ˆ๋Š”๋ฐ ์˜ค๋ฅ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

~$ tsc --version
message TS6029: Version 1.8.0-dev.20151102
~$ cat a.ts
class A {
    get something(): number {return 5;}
    set something(x: any) {}
}

~$ tsc -t es5 a.ts
a.ts(2,2): error TS2380: 'get' and 'set' accessor must have the same type.
a.ts(3,2): error TS2380: 'get' and 'set' accessor must have the same type.

์•„์ด๋Ÿฌ๋‹ˆํ•˜๊ฒŒ๋„ Sublime ๋ฆฐํ„ฐ๋ฅผ ์—…๋ฐ์ดํŠธํ•œ ํ›„ TypeScript 1.7.x๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์˜ค๋ฅ˜๊ฐ€ ๋” ์ด์ƒ ๋ฐœ์ƒํ•˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. ๋‚˜๋Š” ๊ทธ๊ฒƒ์ด 1.7+์—์„œ ๊ณง ๊ฐœ์„ ๋  ๊ฒƒ์ด๋ผ๊ณ  ๊ฐ€์ •ํ•˜๊ณ  ์žˆ์œผ๋ฏ€๋กœ ์•„๋งˆ๋„ 1.8.0์ด ํ‡ด๋ณดํ–ˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

typescript 1.7.5๋ฅผ ์ง€์›ํ•˜๋Š” Visual Studio ์ฝ”๋“œ ๋ฒ„์ „(0.10.5(2015๋…„ 12์›”))๊ณผ ๋‚ด ์ปดํ“จํ„ฐ์— ์ „์—ญ์ ์œผ๋กœ ์„ค์น˜๋œ typescript 1.7.5์—์„œ๋„ ์—ฌ์ „ํžˆ ๋ฌธ์ œ์ž…๋‹ˆ๋‹ค.

image

๊ทธ๋Ÿผ ์–ด๋–ค ๋ฒ„์ „์ด ์ง€์›๋ ๊นŒ์š”?
๊ฐ์‚ฌ ํ•ด์š”

๋Œ„์ด ์ž˜๋ชป ์ƒ๊ฐํ•œ ๊ฒƒ ๊ฐ™์•„์š”. getter์™€ setter๋Š” ๋™์ผํ•œ ์œ ํ˜•์ด์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์ฐฝํ”ผ. ๊ฐ๋„๊ธฐ ํ…Œ์ŠคํŠธ์— ์‚ฌ์šฉํ•  ํŽ˜์ด์ง€ ๊ฐœ์ฒด๋ฅผ ์ž‘์„ฑํ•  ๋•Œ ์ข‹์€ ๊ธฐ๋Šฅ์ด ๋˜์—ˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๋‚˜๋Š” ๊ฐ๋„๊ธฐ ํ…Œ์ŠคํŠธ๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์—ˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค:

po.email = "[email protected]";
expect(po.email).toBe("[email protected]");

... ํŽ˜์ด์ง€ ๊ฐœ์ฒด๋ฅผ ์ž‘์„ฑํ•˜์—ฌ:

class PageObject {
    get email(): webdriver.promise.Promise<string> {
        return element(by.model("ctrl.user.email")).getAttribute("value")
    }
    set email(value: any) {
        element(by.model("ctrl.user.email")).clear().sendKeys(value);
    }
}

๊ทธ ์ฝ”๋“œ๋Š” setter๊ฐ€ any ์œ ํ˜•์ด์–ด์•ผ ํ•ฉ๋‹ˆ๊นŒ?

getter๋Š” webdriver.promise.Promise<string> ๋ฅผ ๋ฐ˜ํ™˜ํ•˜์ง€๋งŒ setter๋Š” string ๊ฐ’์„ ํ• ๋‹นํ•˜๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋” ๊ธด ํ˜•ํƒœ์˜ ๊ฐ๋„๊ธฐ ํ…Œ์ŠคํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋” ๋ช…ํ™•ํ•ด์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

po.email = "[email protected]";
var currentEmail : webdriver.promise.Promise<string> = po.email;
expect(currentEmail).toBe("[email protected]")

@RyanCavanaugh null ์ฃผ์„์˜ ๋„์ž…์œผ๋กœ null์„ ์‚ฌ์šฉํ•˜์—ฌ setter๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ์ผ๋ถ€ ๊ธฐ๋ณธ๊ฐ’์œผ๋กœ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋Š” ์ฝ”๋“œ๋ฅผ ๋ฐฉ์ง€ํ•ฉ๋‹ˆ๋‹ค.

class Style {
    private _width: number = 5;

    // `: number | null` encumbers callers with unnecessary `!`
    get width(): number {
        return this._width;
    }

    // `: number` prevents callers from passing in null
    set width(newWidth: number | null) {
        if (newWidth === null) {
            this._width = 5;
        }
        else {
            this._width = newWidth;
        }
    }
}

| null ๋ฐ | undefined ๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ ์ตœ์†Œํ•œ ์œ ํ˜•์„ ๋‹ค๋ฅด๊ฒŒ ํ—ˆ์šฉํ•˜๋Š” ๊ฒƒ์„ ๊ณ ๋ คํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?

์ด๊ฒƒ์€ ์ •๋ง ์ข‹์€ ๊ธฐ๋Šฅ์ด ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๊ทธ๋Ÿผ ์ด๊ฒŒ ๊ธฐ๋Šฅ์ด ๋ ๊นŒ์š”?

@artyil ๋‹ซํ˜€ ์žˆ๊ณ  _By Design_ ํƒœ๊ทธ๊ฐ€ ์ง€์ •๋˜์–ด ํ˜„์žฌ ์ถ”๊ฐ€ํ•  ๊ณ„ํš์ด ์—†์Œ์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค. ์œ„์— ํ‘œํ˜„๋œ ์šฐ๋ ค ์‚ฌํ•ญ์„ ๋ฌด์‹œํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•˜๋Š” ๊ฐ•๋ ฅํ•œ ์‚ฌ์šฉ ์‚ฌ๋ก€๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ ์ž์œ ๋กญ๊ฒŒ ์‚ฌ๋ก€๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ์œผ๋ฉฐ ์ถ”๊ฐ€ ํ”ผ๋“œ๋ฐฑ์„ ํ†ตํ•ด ํ•ต์‹ฌ ํŒ€์ด ์ž์‹ ์˜ ์ž…์žฅ์„ ์žฌ๊ณ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

@kitsonk ์œ„์˜ ์˜๊ฒฌ์—์„œ ์„ค๋“๋ ฅ ์žˆ๋Š” ์‚ฌ์šฉ ์‚ฌ๋ก€๊ฐ€ ์ถฉ๋ถ„ํžˆ ์ œ๊ณต๋˜์—ˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ํ˜„์žฌ ๋””์ž์ธ์€ ์ด ์ œํ•œ์ด ์žˆ๋Š” ๋Œ€๋ถ€๋ถ„์˜ ๋‹ค๋ฅธ ์œ ํ˜• ์–ธ์–ด์˜ ๊ณตํ†ต ํŒจํ„ด์„ ๋”ฐ๋ฅด์ง€๋งŒ Javascript ์ปจํ…์ŠคํŠธ์—์„œ๋Š” ๋ถˆํ•„์š”ํ•˜๊ณ  ์ง€๋‚˜์น˜๊ฒŒ ์ œํ•œ์ ์ž…๋‹ˆ๋‹ค. ์„ค๊ณ„์— ์˜ํ•œ ๊ฒƒ์ด์ง€๋งŒ ์„ค๊ณ„๊ฐ€ ์ž˜๋ชป๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

๋™์˜ํ•œ๋‹ค.

์ด๊ฒƒ์— ๋Œ€ํ•ด ์ข€ ๋” ์ƒ๊ฐํ•œ ํ›„. ์—ฌ๊ธฐ์„œ ๋ฌธ์ œ๋Š” ์‹ค์ œ๋กœ ๊ตฌํ˜„์˜ ๋ณต์žก์„ฑ์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ๋‚˜๋Š” ๊ฐœ์ธ์ ์œผ๋กœ @Arnavion ์˜ ์˜ˆ์ œ๊ฐ€ ๋งค๋ ฅ์ ์ด๋ผ๊ณ  โ€‹โ€‹์ƒ๊ฐํ•˜์ง€๋งŒ ์˜ค๋Š˜๋‚  ์œ ํ˜• ์‹œ์Šคํ…œ์€ getter/setter๋ฅผ ์ผ๋ฐ˜ ์†์„ฑ์œผ๋กœ ์ทจ๊ธ‰ํ•ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์ด ์ž‘๋™ํ•˜๋ ค๋ฉด ๋‘˜ ๋‹ค ๋™์ผํ•œ ๊ฐ’์„ ๊ฐ€์ ธ์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ฝ๊ธฐ/์“ฐ๊ธฐ ์œ ํ˜•์„ ์ง€์›ํ•˜๋Š” ๊ฒƒ์€ ํฐ ๋ณ€ํ™”๊ฐ€ ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ ์œ ํ‹ธ๋ฆฌํ‹ฐ๊ฐ€ ๊ตฌํ˜„ ๋น„์šฉ์˜ ๊ฐ€์น˜๊ฐ€ ์žˆ๋Š”์ง€ ํ™•์‹ ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

์ €๋Š” TypeScript๋ฅผ ์‚ฌ๋ž‘ํ•˜๊ณ  ํŒ€์ด ๋“ค์ด๋Š” ๋ชจ๋“  ๋…ธ๋ ฅ์— ๊ฐ์‚ฌํ•˜์ง€๋งŒ(์ •๋ง๋กœ, ์—ฌ๋Ÿฌ๋ถ„์€ ๊ธฐ๋ป์š”!), ์ด ๊ฒฐ์ •์— ์‹ค๋งํ–ˆ๋‹ค๋Š” ๊ฒƒ์„ ์ธ์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. getFoo()/setFoo() ๋˜๋Š” get foo()/set foo()/setFooEx() ์˜ ๋Œ€์•ˆ๋ณด๋‹ค ํ›จ์”ฌ ๋” ๋‚˜์€ ์†”๋ฃจ์…˜์ด ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๊ฐ„๋‹จํ•œ ๋ฌธ์ œ ๋ชฉ๋ก:

  • ํ˜„์žฌ ์†์„ฑ์—๋Š” ์ •ํ™•ํžˆ ํ•˜๋‚˜์˜ ์œ ํ˜•์ด ์žˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•ฉ๋‹ˆ๋‹ค. ์ด์ œ ๋ชจ๋“  ์œ„์น˜์— ์žˆ๋Š” ๋ชจ๋“  ์†์„ฑ์˜ "์ฝ๊ธฐ" ์œ ํ˜•๊ณผ "์“ฐ๊ธฐ" ์œ ํ˜•์„ ๊ตฌ๋ณ„ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  • ์†์„ฑ๋‹น ํ•˜๋‚˜๊ฐ€ ์•„๋‹Œ ๋‘ ๊ฐ€์ง€ ์œ ํ˜•์„ ์ถ”๋ก ํ•ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋ชจ๋“  ์œ ํ˜• ๊ด€๊ณ„๊ฐ€ ํ›จ์”ฌ ๋” ๋ณต์žกํ•ด์ง‘๋‹ˆ๋‹ค( { get foo(): string | number; set foo(): boolean } ๋ฅผ { foo: boolean | string | number } $ ์— ํ• ๋‹นํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ? ๋˜๋Š” ๊ทธ ๋ฐ˜๋Œ€๋กœ๋„ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๊นŒ?).
  • ์šฐ๋ฆฌ๋Š” ํ˜„์žฌ ์†์„ฑ์ด ์„ค์ •๋œ ํ›„์—๋„ ๋‹ค์Œ ์ค„์— ์„ค์ •๋œ ๊ฐ’์˜ ์œ ํ˜•์ด ์žˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•ฉ๋‹ˆ๋‹ค(์ผ๋ถ€ ์‚ฌ๋žŒ๋“ค์˜ ์ฝ”๋“œ๋ฒ ์ด์Šค์—์„œ๋Š” ๋ถ„๋ช…ํžˆ ์ž˜๋ชป๋œ ๊ฐ€์ •, ์™€ํŠธ?). ์šฐ๋ฆฌ๋Š” ์•„๋งˆ๋„ ์ด์™€ ๊ฐ™์€ ์†์„ฑ์— ๋Œ€ํ•œ ๋ชจ๋“  ํ๋ฆ„ ์ œ์–ด ๋ถ„์„์„ "๊บผ์•ผ" ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์†”์งํžˆ, ๋‚˜๋Š” ์—ฌ๊ธฐ์—์„œ ์ฝ”๋“œ ์ž‘์„ฑ ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ๊ทœ์ •ํ•˜์ง€ ์•Š์œผ๋ ค๊ณ  ๋…ธ๋ ฅํ•˜์ง€๋งŒ ์ด ์ฝ”๋“œ๊ฐ€

foo.bar = "hello";
console.log(foo.bar);

์ •์ƒ์ ์ธ ์˜๋ฏธ๋ฅผ ๊ฐ€์ง€๋ ค๊ณ  ์‹œ๋„ํ•˜๋Š” ์–ธ์–ด์—์„œ "hello" ๋ณด๋‹ค ๋” ๋งŽ์€ ๊ฒƒ์„ ์ธ์‡„ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์†์„ฑ์€ ํ•„๋“œ์™€ ์™ธ๋ถ€ ๊ด€์ฐฐ์ž๊ฐ€ ๊ตฌ๋ถ„ํ•  ์ˆ˜ ์—†๋Š” ๋™์ž‘์„ ๊ฐ€์ ธ์•ผ ํ•ฉ๋‹ˆ๋‹ค.

@RyanCavanaugh ์ฃผ์ž…๋œ ์˜๊ฒฌ์— ๋™์˜ํ•˜๋Š” ๋™์•ˆ _might_๋Š” ๋งค์šฐ TypeScripty์ผ ์ˆ˜ ์žˆ๋‹ค๋Š” ๋ฐ˜๋Œ€ ์ฃผ์žฅ์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค... setter์—์„œ ์•ฝํ•˜๊ฒŒ ์œ ํ˜•์ด ์ง€์ •๋œ ๋ฌด์–ธ๊ฐ€๋ฅผ ๋˜์ง€์ง€๋งŒ ํ•ญ์ƒ ๊ฐ•๋ ฅํ•œ ์œ ํ˜•์ด ๋ฐ˜ํ™˜๋˜๋Š” ๊ฒƒ, ์˜ˆ:

foo.bar = [ '1', 2 ];  // any[]
console.log(foo.bar);  // number[]: [ 1, 2 ]

๊ฐœ์ธ์ ์œผ๋กœ ๋‚˜๋Š” ๋‹น์‹ ์ด ๊ทธ๋ ‡๊ฒŒ ๋งˆ๋ฒ•์ฒ˜๋Ÿผ ๋  ๊ฒƒ์ด๋ผ๊ณ  ์ƒ๊ฐํ•˜๋Š” ๊ฒฝํ–ฅ์ด ์žˆ์ง€๋งŒ ์ตœ์ข… ๊ฐœ๋ฐœ์ž๊ฐ€ ๋ฌด์—‡์ด ๊ตฌ๋ถ€๋Ÿฌ์ง€๊ณ  ์ ‘ํžˆ๊ณ  ์ž˜๋ฆด ๊ฒƒ์ธ์ง€ ๋ช…ํ™•ํ•˜๊ฒŒ ์ดํ•ดํ•  ์ˆ˜ ์žˆ๋„๋ก ๋ฉ”์†Œ๋“œ๋ฅผ ๋งŒ๋“œ๋Š” ๊ฒƒ์ด ๊ฐ€์žฅ ์ข‹์Šต๋‹ˆ๋‹ค.

๋‹ค์Œ์€ ์ด ๊ธฐ๋Šฅ์˜ ์‚ฌ์šฉ ์‚ฌ๋ก€์ž…๋‹ˆ๋‹ค. API๋Š” _Autocasting_์ด๋ผ๋Š” ๊ธฐ๋Šฅ์„ ๋„์ž…ํ–ˆ์Šต๋‹ˆ๋‹ค. ์ฃผ์š” ์ด์ ์€ ์œ ํ˜•์ด ์ž˜ ์ •์˜๋œ ์†์„ฑ์„ ํ• ๋‹นํ•˜๊ธฐ ์œ„ํ•ด ๊ฐ€์ ธ์˜ฌ ํด๋ž˜์Šค ์ˆ˜๋ฅผ ์ œ๊ฑฐํ•  ์ˆ˜ ์žˆ๋Š” ๊ฐ„์†Œํ™”๋œ ๊ฐœ๋ฐœ์ž ํ™˜๊ฒฝ์ž…๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด ์ƒ‰์ƒ ์†์„ฑ์€ Color ์ธ์Šคํ„ด์Šค ๋˜๋Š” rgba(r, g, b, a) ์™€ ๊ฐ™์€ CSS ๋ฌธ์ž์—ด ๋˜๋Š” 3๊ฐœ ๋˜๋Š” 4๊ฐœ์˜ ์ˆซ์ž ๋ฐฐ์—ด๋กœ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์†์„ฑ์€ ์—ฌ์ „ํžˆ Color ์˜ ์ธ์Šคํ„ด์Šค๋กœ ์ž…๋ ฅ๋ฉ๋‹ˆ๋‹ค. ๊ฐ’์„ ์ฝ์„ ๋•Œ ์–ป๋Š” ์œ ํ˜•์ด๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

๊ทธ๊ฒƒ์— ๋Œ€ํ•œ ๋ช‡ ๊ฐ€์ง€ ์ •๋ณด: https://developers.arcgis.com/javascript/latest/guide/autocasting/index.html

์‚ฌ์šฉ์ž๋Š” ํ•„์š”ํ•œ ๊ฐ€์ ธ์˜ค๊ธฐ ์ˆ˜๋ฅผ ์ค„์—ฌ ํ•ด๋‹น ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜๊ฒŒ ๋˜์–ด ๋งค์šฐ ๊ธฐ๋ปค๊ณ  ํ• ๋‹น ํ›„์— ์œ ํ˜•์ด ๋ณ€๊ฒฝ๋œ๋‹ค๋Š” ์ ์„ ์™„๋ฒฝํ•˜๊ฒŒ ์ดํ•ดํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

์ด ๋ฌธ์ œ์— ๋Œ€ํ•œ ๋˜ ๋‹ค๋ฅธ ์˜ˆ: https://github.com/gulpjs/vinyl#filebase

file.base = 'd:\\dev';
console.log(file.base); //  'd:\\dev'
file.base = null;
console.log(file.base); //  'd:\\dev\\vinyl' (returns file.cwd)

๋”ฐ๋ผ์„œ setter๋Š” string | null | undefined ์ด๊ณ  getter๋Š” string ์ž…๋‹ˆ๋‹ค. ์ด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ์œ ํ˜• ์ •์˜์—์„œ ์–ด๋–ค ์œ ํ˜•์„ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๊นŒ? ์ „์ž๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ ์ปดํŒŒ์ผ๋Ÿฌ๋Š” ๋ชจ๋“  ๊ณณ์—์„œ ์“ธ๋ชจ์—†๋Š” null ๊ฒ€์‚ฌ๋ฅผ ์š”๊ตฌํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ํ›„์ž๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ด ์†์„ฑ์— null ๋ฅผ ํ• ๋‹นํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

getter๊ฐ€ nullable์„ ๋ฐ˜ํ™˜ํ•˜๊ธฐ๋ฅผ ์›ํ•˜์ง€๋งŒ setter๊ฐ€ null์„ ์ž…๋ ฅ์œผ๋กœ ํ—ˆ์šฉํ•˜์ง€ ์•Š์•„์•ผ ํ•˜๋Š” ๋˜ ๋‹ค๋ฅธ ์˜ˆ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

class Memory {
    public location: string;
    public time: Date;
    public company: Person[];
}

class Person
{
    private _bestMemoryEver: Memory | null;

    public get bestMemoryEver(): Memory | null { // Might not have one yet
        return this._bestMemoryEver;
    }

    public set bestMemoryEver(memory: Memory) { // But when he/she gets one, it can only be replaced, not removed
        this._bestMemoryEver = memory;
    }
}

var someDude = new Person();
// ...
var bestMemory: Memory | null = someDude.bestMemoryEver;
//...
someDude.bestMemoryEver = null; // Oh no you don't!

null์— ๋Œ€ํ•ด getter/setter๋ฅผ ๋‹ค๋ฅด๊ฒŒ ํ•˜๊ธฐ ์œ„ํ•œ ๋ช‡ ๊ฐ€์ง€ ํŠน๋ณ„ํ•œ ๋…ผ๋ฆฌ๋ฅผ ๊ตฌ์ถ•ํ•˜๋Š” ๊ฒƒ์ด ๋„ˆ๋ฌด ๋งŽ์€ ์ž‘์—…์ผ ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ์ดํ•ดํ•˜๊ณ , ๋‚˜์—๊ฒŒ๋Š” ๊ทธ๋ ‡๊ฒŒ ํฐ ๋ฌธ์ œ๊ฐ€ ์•„๋‹ˆ์ง€๋งŒ ์žˆ์œผ๋ฉด ์ข‹์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

@Elephant-Vessel ์ฒ ํ•™์ ์œผ๋กœ ๋‚˜๋Š” ์ด ์˜ˆ๋ฅผ ์ ˆ๋Œ€์ ์œผ๋กœ ์ข‹์•„ํ•ฉ๋‹ˆ๋‹ค. ์ธ๊ฐ„์˜ ๋ณ€๋•์Šค๋Ÿฌ์šด ๋ณธ์„ฑ์„ ์ž˜ ๋‚˜ํƒ€๋‚ด์ง€ null (๋˜๋Š” undefined )์„ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค. ์‹œ์Šคํ…œ์—์„œ ์‹œ๋ƒ…์Šค ์žฅ์• ๋ฅผ ์–ด๋–ป๊ฒŒ ๋ชจ๋ธ๋งํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?

@aluanhaddad ์™œ ์‹œ๋ƒ…์Šค ์‹คํŒจ๋ฅผ ์›ํ•ฉ๋‹ˆ๊นŒ? ๋‚˜๋Š” ๋‚ด ์šฐ์ฃผ์—์„œ ๊ทธ๋Ÿฐ ์ข…๋ฅ˜์˜ ๋‚˜์œ ๊ฒƒ์„ ์›ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค ;)

์ด์— ๋Œ€ํ•œ ์—…๋ฐ์ดํŠธ๊ฐ€ ์žˆ์Šต๋‹ˆ๊นŒ? null ๋˜๋Š” undefined๋กœ ์„ค์ •๋  ๋•Œ ๊ธฐ๋ณธ๊ฐ’ ์„ ๊ฐ–๋Š” ๊ฒƒ์€ ์–ด๋–ป์Šต๋‹ˆ๊นŒ?

๋‚˜๋Š” ์†Œ๋น„์ž๊ฐ€ ์‚ฌ์ „์— null ์ฒดํฌ๋ฅผ ํ•˜๋Š” ๊ฒƒ์„ ์›ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ํ˜„์žฌ๋Š” ๋Œ€์‹  setter๋ฅผ ๋ณ„๋„์˜ ๋ฉ”์†Œ๋“œ๋กœ ๋งŒ๋“ค์–ด์•ผ ํ•˜๋Š”๋ฐ ๋™์ผํ•˜๊ฒŒ ํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค.

๋‹ค์Œ์€ ๋‚ด๊ฐ€ ๊ฐ–๊ณ  ์‹ถ์€ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

export class TestClass {
  private _prop?: number;

  get prop(): number {
    // return default value if not defined
    this._prop === undefined ? 0 : this._prop;
  }
  set prop(val: number | undefined) {
    this._prop = val;
  }
}

Null์ด ์•„๋‹Œ ๊ฒ€์‚ฌ์˜ ์ด์ ์€ ๋ฌธ์ œ์™€ ํ•จ๊ป˜ ์ œ๊ณต๋˜๋ฉฐ ์ด๊ฒƒ์ด ๊ทธ ์ค‘ ํ•˜๋‚˜์ธ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ์—„๊ฒฉํ•œ null ๊ฒ€์‚ฌ๋ฅผ ๋„๋ฉด ์ด๊ฒƒ์ด ๊ฐ€๋Šฅํ•˜์ง€๋งŒ null ์ฐธ์กฐ ์˜ˆ์™ธ๋ฅผ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•œ ์ปดํŒŒ์ผ๋Ÿฌ์˜ ๋„์›€์„ ๋ฐ›์ง€ ๋ชปํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ปดํŒŒ์ผ๋Ÿฌ ์ง€์›์„ ์›ํ•œ๋‹ค๋ฉด ์ตœ์†Œํ•œ null ํ—ˆ์šฉ ์—ฌ๋ถ€์™€ ๊ด€๋ จํ•˜์—ฌ getter ๋ฐ setter์— ๋Œ€ํ•œ ๋ณ„๋„์˜ ์ •์˜๋ฅผ ๊ฐ–๋Š” ๊ฒƒ๊ณผ ๊ฐ™์€ ๋” ๋งŽ์€ ์ง€์›์ด ์ œ๊ณต๋˜์–ด์•ผ ํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

๋ฌธ์ œ์˜ ๋ ˆ์ด๋ธ”์€ ์ด๊ฒƒ์ด ์„ค๊ณ„ ์ œํ•œ์ด๋ฉฐ ๊ตฌํ˜„์ด ๋„ˆ๋ฌด ๋ณต์žกํ•œ ๊ฒƒ์œผ๋กœ ๊ฐ„์ฃผ๋  ์ˆ˜ ์žˆ์Œ์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค. ์ด๋Š” ๋ณธ์งˆ์ ์œผ๋กœ ๋ˆ„๊ตฐ๊ฐ€๊ฐ€ ์ด๊ฒƒ์ด ์‚ฌ์‹ค์ด์–ด์•ผ ํ•˜๋Š” ๋งค์šฐ ๊ฐ•๋ ฅํ•œ ์ด์œ ๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ ์•„๋ฌด๋ฐ๋„ ๊ฐ€์ง€ ์•Š๋Š”๋‹ค๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

@mhegazy @kitsonk ํŽธ๊ฒฌ์ด ์žˆ์„ ์ˆ˜ ์žˆ์ง€๋งŒ, ์ด๊ฒƒ์€ ํŠนํžˆ ์•„์ง null ๊ฒ€์‚ฌ๊ฐ€ ์—†๋Š” ์–ธ์–ด์™€ ๊ฐ™์€ ๋‹ค๋ฅธ ์ค‘๊ด„ํ˜ธ์—์„œ ์ผ๋ฐ˜์ ์ธ ํŒจํ„ด์— ๋Œ€ํ•œ ์—„๊ฒฉํ•œ null ๊ฒ€์‚ฌ๋ฅผ ์œ„ํ•ด ๋ฐœ์ƒํ•œ ๋ฒ„๊ทธ ๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์€ ์†Œ๋น„์ž๊ฐ€ ๊ฐ•ํƒ€ ์—ฐ์‚ฐ์ž๋ฅผ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜ ์‹ค์ œ๋กœ null์ด ์•„๋‹Œ์ง€ ํ™•์ธํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค(๊ธฐ๋ณธ๊ฐ’์„ ์‚ฌ์šฉํ•˜์—ฌ null์ด ๋˜์ง€ ์•Š๋Š”๋‹ค๋Š” ์ ).

์ด๊ฒƒ์€ ๊ธฐ์ˆ ์ ์œผ๋กœ ๋‹ค๋ฅธ ์œ ํ˜•์ด๊ธฐ ๋•Œ๋ฌธ์— ์—„๊ฒฉํ•œ null ๊ฒ€์‚ฌ๋ฅผ ์ถ”๊ฐ€ํ•˜๋ฉด ๋ฌธ์ œ๊ฐ€ ํ•ด๊ฒฐ๋ฉ๋‹ˆ๋‹ค. ๋‚˜๋Š” ๊ฐ•๋ ฅํ•œ ๋‹ค๋ฅธ ์œ ํ˜•์„ ์„ค์ •ํ•˜๋„๋ก ์š”๊ตฌํ•˜์ง€ ์•Š์ง€๋งŒ ์ด๋ฅผ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•˜๋Š” ๋””์ž์ธ ์š”๊ตฌ ์‚ฌํ•ญ์€ ๊ฐ•๋ ฅํ•œ ๋‹ค๋ฅธ ์œ ํ˜•๋„ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•˜๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

null ๋ฐ undefined์™€ ๊ฐ™์€ ์œ ํ˜•์ด ์™„์ „ํžˆ ๋‹ค๋ฅธ ์œ ํ˜•์„ ํ™œ์„ฑํ™”ํ•˜์ง€ ์•Š์œผ๋ ค๋Š” ๊ฒฝ์šฐ ์ธํ„ฐํŽ˜์ด์Šค ์ •์˜ ๋ฐ d.ts ํŒŒ์ผ์— ๋Œ€ํ•ด ํŠน์ˆ˜ํ•œ ๊ฒฝ์šฐ๊ฐ€ ๋˜๋„๋ก ์•ฝํ•œ ์œ ํ˜•์— ๋Œ€์ฒด ๋””์ž์ธ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

https://github.com/Microsoft/TypeScript/issues/2521#issuecomment -199650959์— ๋Œ€ํ•œ ์‘๋‹ต์œผ๋กœ
๊ตฌํ˜„ํ•˜๊ธฐ๊ฐ€ ๋œ ๋ณต์žกํ•ด์•ผ ํ•˜๋Š” ์ œ์•ˆ ๋””์ž์ธ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

export interface Test {
  undefset prop1: number; // property [get] type number and [set] type number | undefined
  nullset prop2: number; // property [get] type number and [set] type number | null
  nilset prop3: number; // property [get] type number and [set] type number | null | undefined
  undefget prop4: number; // property [get] type number | undefined and [set] type number
  nullget prop5: number; // property [get] type number | null and [set] type number
  nilget prop6: number; // property [get] type number | null | undefined and [set] type number
}

TypeScript์— ํ›จ์”ฌ ๋” ์ต์ˆ™ํ•œ ์ด ์Šค๋ ˆ๋“œ๋ฅผ ๋ณด๊ณ  ์žˆ๋Š” ์‚ฌ๋žŒ๋“ค์ด ์žˆ๋Š” ๊ฒƒ ๊ฐ™์œผ๋ฏ€๋กœ ์—ฌ์ „ํžˆ ๊ด€์‹ฌ์„ ๊ฐ–๊ณ  ์žˆ๋Š” ๋ˆ„๊ตฐ๊ฐ€๊ฐ€ ๊ด€๋ จ ์งˆ๋ฌธ์— ๋‹ต๋ณ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด Cesium ๋ฌธ์ œ ์—์„œ ์ €๋Š” ์—ฌ๊ธฐ์„œ ๋…ผ์˜ํ•˜๊ณ  ์žˆ๋Š” get/set ์œ ํ˜• ์ œํ•œ์— ๋Œ€ํ•ด ์–ธ๊ธ‰ํ–ˆ์œผ๋ฉฐ Cesium ์‚ฌ๋žŒ๋“ค์€ ๊ทธ๋“ค์ด ๋”ฐ๋ฅด๊ณ  ์žˆ๋Š” ํŒจํ„ด์ด C#์—์„œ ์˜จ ๊ฒƒ์ด๋ผ๊ณ  ๋งํ–ˆ์Šต๋‹ˆ๋‹ค -- ์ด๊ฒƒ์€ ์•”์‹œ์  ์ƒ์„ฑ์ž ์ž…๋‹ˆ๋‹ค.

TypeScript๊ฐ€ ์•”์‹œ์  ์ƒ์„ฑ์ž๋ฅผ ์ง€์›ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ? ์ฆ‰, myThing.foo ๋Š” ํ•ญ์ƒ Bar Bar ๋ฅผ ์ง์ ‘ ํ• ๋‹นํ•  ์ˆ˜ ์žˆ์ง€๋งŒ number ๋ฅผ ํ• ๋‹นํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฐœ๋ฐœ์ž์˜ ํŽธ์˜๋ฅผ ์œ„ํ•ด Bar ์— ์กฐ์šฉํžˆ ๋ž˜ํ•‘/์ดˆ๊ธฐํ™”ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉํ•˜์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ? Bar ์ฃผ์„์„ ๋‹ฌ๊ฑฐ๋‚˜ " number is assignable to Bar<number> "๋ผ๊ณ  ๊ตฌ์ฒด์ ์œผ๋กœ ๋งํ•˜๋ฉด Cesium ๋ฌธ์ œ์—์„œ ๋…ผ์˜๋œ ์‚ฌ์šฉ ์‚ฌ๋ก€๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ด ์Šค๋ ˆ๋“œ์—์„œ ์ œ๊ธฐ๋œ ๋งŽ์€ ๋ฌธ์ œ๋“ค.

๊ทธ๋ ‡์ง€ ์•Š์€ ๊ฒฝ์šฐ ๋ณ„๋„์˜ ๋ฌธ์ œ์—์„œ ์•”์‹œ์  ์ƒ์„ฑ์ž ์ง€์›์„ ์ œ์•ˆํ•ด์•ผ ํ•ฉ๋‹ˆ๊นŒ?

๊ทธ๊ฒƒ์— ๋Œ€ํ•ด ๋” ๋งŽ์ด ์ƒ๊ฐํ•˜๊ฑฐ๋‚˜ ์ฝ์„์ˆ˜๋ก "์•”์‹œ์  ์ƒ์„ฑ์ž ํŒจํ„ด"์— ์ด ํ˜ธ์—์„œ ์„ค๋ช…ํ•˜๋Š” ๊ธฐ๋Šฅ์ด ํ•„์š”ํ•˜๋‹ค๋Š” ํ™•์‹ ์ด ๋” ๋งŽ์ด ๋“ญ๋‹ˆ๋‹ค. ๋ฐ”๋‹๋ผ JS์—์„œ ๊ฐ€๋Šฅํ•œ ์œ ์ผํ•œ ๋ฐฉ๋ฒ•์€ ๊ฐ์ฒด get/set ์ ‘๊ทผ์ž๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์™œ๋ƒํ•˜๋ฉด ๋ช…๋ชฉ ํ• ๋‹น( = ์—ฐ์‚ฐ์ž)์ด ์‹ค์ œ๋กœ ์‚ฌ์šฉ์ž ์ •์˜ ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ์œ ์ผํ•œ ์‹œ๊ฐ„์ด๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. (๋งž๋‚˜?) ๊ทธ๋ž˜์„œ ์šฐ๋ฆฌ์—๊ฒŒ ์ •๋ง ํ•„์š”ํ•  ๊ฒƒ ๊ฐ™์•„

class MyThing{
  set foo(b: Bar<boolean> | boolean);
  get foo(): Bar<boolean>;
}

@RyanCavanaugh ๊ฐ€ "์ œ์ •์‹ ์˜ ์˜๋ฏธ๋ก "์ด ์•„๋‹ˆ๋ผ๊ณ  ์ƒ๊ฐํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋“ค๋ฆฝ๋‹ˆ๋‹ค.

๊ฐ„๋‹จํ•œ ์‚ฌ์‹ค์€ ์ด ํŒจํ„ด์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฝค ์ธ๊ธฐ ์žˆ๋Š” JS ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ์žˆ์œผ๋ฉฐ ์ฃผ์–ด์ง„ ๊ธฐ์กด TS ์ œ์•ฝ ์กฐ๊ฑด์„ ์„ค๋ช…ํ•˜๋Š” ๊ฒƒ์ด ๋ถˆ๊ฐ€๋Šฅํ•˜์ง€๋Š” ์•Š๋”๋ผ๋„ ์–ด๋ ค์šด ๊ฒƒ์ฒ˜๋Ÿผ ๋ณด์ž…๋‹ˆ๋‹ค. ๋‚ด๊ฐ€ ํ‹€๋ ธ์œผ๋ฉด ์ข‹๊ฒ ์–ด.

JavaScript๋Š” ์ด๋ฏธ ์„ค๋ช…ํ•˜๋Š” ํŒจํ„ด์„ ํ—ˆ์šฉํ•ฉ๋‹ˆ๋‹ค. _challenge_๋Š” TypeScript์—์„œ ์œ ํ˜•์˜ ์ฝ๊ธฐ ๋ฐ ์“ฐ๊ธฐ ์ธก๋ฉด์ด ์„ค๊ณ„์ƒ ๋™์ผํ•œ ๊ฒƒ์œผ๋กœ ๊ฐ€์ •๋œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ํ• ๋‹น์„ ํ—ˆ์šฉํ•˜์ง€ ์•Š๋Š” ์–ธ์–ด ์ˆ˜์ •( readonly )์ด ์žˆ์—ˆ์ง€๋งŒ _์“ฐ๊ธฐ ์ „์šฉ_ ๊ฐœ๋…์„ ์š”์ฒญํ•œ ๋ช‡ ๊ฐ€์ง€ ๋ฌธ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๊ฐœ๋…์€ ์‹ค์ œ ๊ฐ€์น˜์— ๋น„ํ•ด ๋„ˆ๋ฌด ๋ณต์žกํ•˜๋‹ค๊ณ  ๋…ผ์˜๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

IMO, JavaScript๊ฐ€ ์ ‘๊ทผ์ž๋ฅผ ํ—ˆ์šฉํ•œ ์ดํ›„๋กœ ์‚ฌ๋žŒ๋“ค์€ ์ž ์žฌ์ ์œผ๋กœ ๊ทธ๋“ค๊ณผ ํ˜ผ๋™๋˜๋Š” API๋ฅผ ๋งŒ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค. ์ €๋Š” ๊ฐœ์ธ์ ์œผ๋กœ ํ• ๋‹น๋œ ๊ฒƒ์ด _๋งˆ์ˆ ์ ์œผ๋กœ_ ๋‹ค๋ฅธ ๊ฒƒ์œผ๋กœ ๋ณ€๊ฒฝ๋˜๋Š” ๊ฒƒ์ด ํ˜ผ๋ž€์Šค๋Ÿฝ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ์•”์‹œ์ ์ธ ๋ชจ๋“  ๊ฒƒ, ํŠนํžˆ ์œ ํ˜• ๋ณ€ํ™˜์€ JavaScript IMO์˜ ๊ณจ์นซ๊ฑฐ๋ฆฌ์ž…๋‹ˆ๋‹ค. ๋ฌธ์ œ๋ฅผ ์ผ์œผํ‚ค๋Š” ๊ฒƒ์€ ๋ฐ”๋กœ ์œ ์—ฐ์„ฑ์ž…๋‹ˆ๋‹ค. _magic_์ด ์žˆ๋Š” ์ด๋Ÿฌํ•œ ์œ ํ˜•์˜ ๋ณ€ํ™˜์—์„œ๋Š” ๊ฐœ์ธ์ ์œผ๋กœ ๋ฉ”์„œ๋“œ๊ฐ€ ํ˜ธ์ถœ๋˜๋Š” ๊ฒƒ์„ ๋ณด๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ ์ผ์ข…์˜ โœจ๊ฐ€ ๋ฐœ์ƒํ•˜๊ณ  ๊ฐ’์„ ๊ฒ€์ƒ‰ํ•˜๊ธฐ ์œ„ํ•ด ์ฝ๊ธฐ ์ „์šฉ getter๋ฅผ ๋งŒ๋“œ๋Š” ๊ฒƒ์ด ์†Œ๋น„์ž์—๊ฒŒ ์ข€ ๋” ๋ช…์‹œ์ ์ž…๋‹ˆ๋‹ค.

์ด๋Š” ์‹ค์ œ ์‚ฌ์šฉ์ด ์กด์žฌํ•˜์ง€ ์•Š๋Š”๋‹ค๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•˜์ง€ ์•Š์œผ๋ฉฐ, ์ด๋Š” ์ž ์žฌ์ ์œผ๋กœ ์ œ์ •์‹ ์ด๊ณ  ํ•ฉ๋ฆฌ์ ์ž…๋‹ˆ๋‹ค. ์ „์ฒด ์œ ํ˜• ์‹œ์Šคํ…œ์„ ๋‘ ๊ฐœ๋กœ ๋ถ„ํ• ํ•˜๋Š” ๋ณต์žก์„ฑ ๋•Œ๋ฌธ์— ์œ ํ˜•์ด ์ฝ๊ธฐ ๋ฐ ์“ฐ๊ธฐ ์กฐ๊ฑด์—์„œ ์ถ”์ ๋˜์–ด์•ผ ํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๊ฒƒ์€ ๋งค์šฐ ์‚ฌ์†Œํ•˜์ง€ ์•Š์€ ์‹œ๋‚˜๋ฆฌ์˜ค์ฒ˜๋Ÿผ ๋ณด์ž…๋‹ˆ๋‹ค.

๋‚˜๋Š” :sparkles: here์— ๋™์˜ํ•ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ํŒจํ„ด ์‚ฌ์šฉ์— ๋Œ€ํ•ด ์ฐฌ์„ฑํ•˜๊ฑฐ๋‚˜ ๋ฐ˜๋Œ€ํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹™๋‹ˆ๋‹ค. ๋‹จ์ง€ ์ด๋ฏธ ํŒจํ„ด์„ ์‚ฌ์šฉ ํ•˜๊ณ  ํŒจํ„ด์˜ ๋ชจ์–‘์„ ์„ค๋ช…ํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ๋”ฐ๋ผ๊ฐ€๋ ค๊ณ  ํ•  ๋ฟ์ž…๋‹ˆ๋‹ค. ๊ทธ๊ฒƒ์€ ์ด๋ฏธ ์ž‘๋™ํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ์ž‘๋™ํ•˜๋ฉฐ TS๋Š” ์ด๋ฅผ ์„ค๋ช…ํ•  ๋„๊ตฌ๋ฅผ ์ œ๊ณตํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์ข‹๋“  ๋‚˜์˜๋“  JS๋Š” ํ• ๋‹น์„ ํ•จ์ˆ˜ ํ˜ธ์ถœ๋กœ ๋ฐ”๊ฟ€ ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ–ˆ์œผ๋ฉฐ ์‚ฌ๋žŒ๋“ค์€ ์ด๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. set/get ์Œ์— ๋‹ค๋ฅธ ์œ ํ˜•์„ ํ• ๋‹นํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋Šฅ์ด ์—†๋Š”๋ฐ ์™œ ์•ฐ๋น„์–ธํŠธ ํƒ€์ดํ•‘์— set/get ๊ฐ€ ์žˆ์Šต๋‹ˆ๊นŒ? Salsa๋Š” myThing.foo ๊ฐ€ ํ• ๋‹น์˜ ์–ด๋Š ์ชฝ์— ์žˆ๋Š”์ง€์— ๊ด€๊ณ„์—†์ด ํ•ญ์ƒ ๋‹จ์ผ ์œ ํ˜•์˜ ๋ฉค๋ฒ„ ๋ณ€์ˆ˜๋กœ ์ฒ˜๋ฆฌํ•˜๋ ค๋Š” ๊ฒฝ์šฐ ์†์„ฑ์ด getter ๋ฐ setter๋กœ ๊ตฌํ˜„๋œ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. (๋ฌผ๋ก  ์‹ค์ œ TypeScript ์ปดํŒŒ์ผ์€ ์™„์ „ํžˆ ๋‹ค๋ฅธ ๊ฒƒ์ž…๋‹ˆ๋‹ค.)

@thw0rted

TypeScript์— ํ›จ์”ฌ ๋” ์ต์ˆ™ํ•œ ์ด ์Šค๋ ˆ๋“œ๋ฅผ ๋ณด๊ณ  ์žˆ๋Š” ์‚ฌ๋žŒ๋“ค์ด ์žˆ๋Š” ๊ฒƒ ๊ฐ™์œผ๋ฏ€๋กœ ์—ฌ์ „ํžˆ ๊ด€์‹ฌ์„ ๊ฐ–๊ณ  ์žˆ๋Š” ๋ˆ„๊ตฐ๊ฐ€๊ฐ€ ๊ด€๋ จ ์งˆ๋ฌธ์— ๋‹ต๋ณ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด Cesium ๋ฌธ์ œ์—์„œ ์ €๋Š” ์—ฌ๊ธฐ์„œ ๋…ผ์˜ํ•˜๊ณ  ์žˆ๋Š” get/set ์œ ํ˜• ์ œํ•œ์— ๋Œ€ํ•ด ์–ธ๊ธ‰ํ–ˆ์œผ๋ฉฐ Cesium ์‚ฌ๋žŒ๋“ค์€ ๊ทธ๋“ค์ด ๋”ฐ๋ฅด๋Š” ํŒจํ„ด์ด C#์—์„œ ์˜จ ๊ฒƒ์ด๋ผ๊ณ  ๋งํ–ˆ์Šต๋‹ˆ๋‹ค -- ์ด๊ฒƒ์€ ์•”์‹œ์  ์ƒ์„ฑ์ž์ž…๋‹ˆ๋‹ค.

C#์˜ ์•”์‹œ์  ์‚ฌ์šฉ์ž ์ •์˜ ๋ณ€ํ™˜ ์—ฐ์‚ฐ์ž๋Š” ๊ฐ’ ์œ ํ˜•์„ ๊ธฐ๋ฐ˜์œผ๋กœ ์ •์  ์ฝ”๋“œ ์ƒ์„ฑ์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค. TypeScript ์œ ํ˜•์€ ์ง€์›Œ์ง€๊ณ  ๋Ÿฐํƒ€์ž„ ๋™์ž‘์— ์˜ํ–ฅ์„ ์ฃผ์ง€ ์•Š์Šต๋‹ˆ๋‹ค($ Promise ํด๋ฆฌํ•„๋Ÿฌ์˜ ๊ฒฝ์šฐ async / await #$ ์˜ˆ์™ธ ์ผ€์ด์Šค๋Š” ๊ฒฌ๋”œ ์ˆ˜ ์—†์Œ).

@kitsonk ์†์„ฑ๊ณผ ๊ด€๋ จํ•˜์—ฌ ์ผ๋ฐ˜์ ์œผ๋กœ ๋™์˜ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. Java, C++ ๋ฐ C#์„ ์‚ฌ์šฉํ•˜์—ฌ ์ƒ๋‹นํ•œ ์‹œ๊ฐ„์„ ๋ณด๋ƒˆ์ง€๋งŒ ์ค‘์š”ํ•œ ๊ตฌ๋ฌธ ์ถ”์ƒํ™”๋ฅผ ์ œ๊ณตํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์†์„ฑ(C#์—์„œ ๋ณผ ์ˆ˜ ์žˆ์Œ)์„ ์ ˆ๋Œ€์ ์œผ๋กœ ์ข‹์•„ํ•ฉ๋‹ˆ๋‹ค(JavaScript์—์„œ๋Š” ๋‹ค์†Œ ์‚ฌ์‹ค์ž„). ์ด๋ฅผ ํ†ตํ•ด ์ธํ„ฐํŽ˜์ด์Šค๋Š” ๊ตฌ๋ฌธ์„ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š๊ณ ๋„ ์˜๋ฏธ ์žˆ๋Š” ๋ฐฉ์‹์œผ๋กœ ์ฝ๊ธฐ/์“ฐ๊ธฐ ๊ธฐ๋Šฅ์„ ๋ถ„๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋‚˜๋Š” X ๋ฅผ ์–ป๋Š” ๊ฒƒ์ด ์•”์‹œ์ ์ผ ์ˆ˜ ์žˆ์„ ๋•Œ getX() ์™€ ๊ฐ™์€ ์‚ฌ์†Œํ•œ ์ž‘์—…์— ๋™์‚ฌ๊ฐ€ ๋‚ญ๋น„๋˜๋Š” ๊ฒƒ์„ ๋ณด๋Š” ๊ฒƒ์„ ์‹ซ์–ดํ•ฉ๋‹ˆ๋‹ค.
IMO์˜ ํ˜ผ๋ž€์Šค๋Ÿฌ์šด API๋Š” ์ ‘๊ทผ์ž๋ฅผ ๋‚จ์šฉํ•œ๋‹ค๊ณ  ํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋„ˆ๋ฌด ๋งŽ์€ _setters_๊ฐ€ ๋งˆ๋ฒ• ๊ฐ™์€ ์ผ์„ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋” ๋งŽ์ด ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

์ฝ๊ธฐ ์ „์šฉ์ด์ง€๋งŒ ์ผ๋ถ€ ๋ฐ์ดํ„ฐ์— ๋Œ€ํ•œ ๋ผ์ด๋ธŒ ๋ทฐ(์˜ˆ: registry )๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ ์ฝ๊ธฐ ์ „์šฉ ์†์„ฑ์„ ์ดํ•ดํ•˜๊ธฐ๊ฐ€ ๋งค์šฐ ์‰ฝ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

interface Entry {key: string; value: any;}

export function createRegistry() {
  let entries: Entry[] = [];
  return {
    register(key: string, value: any) {
      entries = [...entries, {key, value}];
    },
    get entries() {
      return [...entries];
    }
  }
}

const registry = createRegistry();

registry.register('hello', 'ๆ‚จๅฅฝ');
console.log(registry.entries); //[{key: 'hello', value: 'ๆ‚จๅฅฝ'}]
registry.register('goodbye', 'ๅ†่ง');
console.log(registry.entries); //[{key: 'hello', value: 'ๆ‚จๅฅฝ'}, {key: 'goodbye', value: 'ๅ†่ง'}]

์ ‘์„ ์— ๋Œ€ํ•ด ๋ฏธ์•ˆํ•˜์ง€๋งŒ ๋‚˜๋Š” ์ด๊ฒƒ์— ๋Œ€ํ•œ ์ ‘๊ทผ์ž๋ฅผ ์ข‹์•„ํ•˜๊ณ  ์ดํ•ดํ•˜๊ธฐ ์‰ฝ๋‹ค๊ณ  ์ƒ๊ฐํ•˜์ง€๋งŒ ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ๊ธฐ๊บผ์ด ํ™•์‹ ํ•˜๊ณ  ๊ฐ€๋…์„ฑ์ด ๋‚˜์˜ ์ฒซ ๋ฒˆ์งธ ๊ด€์‹ฌ์‚ฌ์ž…๋‹ˆ๋‹ค.

TypeScript๊ฐ€ JavaScript๋ฅผ ์ œํ•œํ•˜๋ฉด ์ด์ ๋ณด๋‹ค ์„ฑ๊ฐ€์‹  ๊ฒƒ์ด ๋” ๋งŽ์Šต๋‹ˆ๋‹ค. TypeScript๋Š” ๊ฐœ๋ฐœ์ž๊ฐ€ ์„œ๋กœ ์˜์‚ฌ ์†Œํ†ตํ•  ์ˆ˜ ์žˆ๋„๋ก ๋„์™€์ฃผ๋Š” ๊ฒƒ์ด ์•„๋‹Œ๊ฐ€์š”?

๋˜ํ•œ ์„ธํ„ฐ๋ฅผ ๋ฎคํ…Œ์ดํ„ฐ๋ผ๊ณ  ๋ถ€๋ฅด๋Š” ๋ฐ๋Š” ์ด์œ ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์–ด๋–ค ์ข…๋ฅ˜์˜ ๋ณ€ํ™˜๋„ ํ•„์š”ํ•˜์ง€ ์•Š๋‹ค๋ฉด setter๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  ์ง์ ‘ ๋ณ€์ˆ˜๋ฅผ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.

์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ํ”„๋กœ์ ํŠธ๋ฅผ typescript๋กœ ํฌํŒ…. ๋‚˜๋Š”์ด ๋ฌธ์ œ๋ฅผ ๋งŒ๋‚ฌ๋‹ค..

์ด๊ฒƒ์€ ๊ฐ๋„ @Input ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ์—์„œ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. ๊ฐ’์ด ํ…œํ”Œ๋ฆฟ์—์„œ ์ „๋‹ฌ๋˜๊ธฐ ๋•Œ๋ฌธ์— ๋‹ค๋ฅธ ๋“ค์–ด์˜ค๋Š” ๊ฐœ์ฒด ์œ ํ˜•์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฒƒ์ด ํ›จ์”ฌ ๋” ๊น”๋”ํ•ด์ง‘๋‹ˆ๋‹ค.

์—…๋ฐ์ดํŠธ: ์ด๊ฒƒ์€ ๋‚˜๋ฅผ ์œ„ํ•ด ์ž‘๋™ํ•˜๋Š” ๊ฒƒ์œผ๋กœ ๋ณด์ž…๋‹ˆ๋‹ค.

import { Component, Input } from '@angular/core';
import { flatMap, isString, isArray, isFalsy } from 'lodash';

@Component({
  selector: 'app-error-notification',
  templateUrl: './error-notification.component.html',
})

export class ErrorNotificationComponent {
  private _errors: Array<string> = [];
  constructor() { }
  /**
   * 'errors' is expected to be an input of either a string or an array of strings
   */
  @Input() set errors(errors: Array<string> | any){
      // Caller just passed in a string instead of an array of strings
      if (isString(errors)) {
        this._errors = [errors];
      }
      // Caller passed in array, assuming it is a string array
      if (isArray(errors)) {
        this._errors = errors;
      }
      // Caller passed in something falsy, which means we should clear error list
      if (isFalsy(errors)) {
        this._errors = [];
      }
      // At this point just set it to whatever might have been passed in and let
      // the user debug when it is broken.
      this._errors = errors;
  }

  get errors() {
    return this._errors;
  }
}

์šฐ๋ฆฌ๋„ ๊ทธ๋žฌ๋‚˜์š”? setter์™€ getter๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋‹ค๋ฅธ ์œ ํ˜•์„ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฐ€๋Šฅ์„ฑ์„ ์ •๋ง๋กœ ๊ฐ–๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด:

class Field {
  private _value: string;

  get value(): string {
    return this._value;
  }

  set value(value: any) {
    this._value = String(value);
  }
}

์ด๊ฒƒ์€ ๋„ค์ดํ‹ฐ๋ธŒ ๊ตฌํ˜„์˜ 99%๋ฅผ ์ˆ˜ํ–‰ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค( (input as HTMLInputElement).value ์— ์ˆซ์ž๋ฅผ ์ „๋‹ฌํ•˜๋ฉด ํ•ญ์ƒ ๋ฌธ์ž์—ด์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ์‚ฌ์‹ค get ๋ฐ set ์€ ๋ฉ”์„œ๋“œ๋กœ ๊ฐ„์ฃผ๋˜์–ด์•ผ ํ•˜๋ฉฐ ์ผ๋ถ€๋ฅผ ํ—ˆ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

set value(value: string);
set value(value: number);
set value(value: any) {
  this._value = String(value);
}
  // AND/OR
set value(value: string | number) {
  this._value = String(value);
}

@raysuelzer , ์ฝ”๋“œ๊ฐ€ "์ž‘๋™"ํ•œ๋‹ค๊ณ  ๋งํ•  ๋•Œ ErrorNotificationComponent.errors ๋Š” Array<string> | any ์œ ํ˜•์„ ๋ฐ˜ํ™˜ํ•˜์ง€ ์•Š์Šต๋‹ˆ๊นŒ? ์ฆ‰, ์‹ค์ œ๋กœ Array<string> ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ ๋•Œ ์‚ฌ์šฉํ•  ๋•Œ๋งˆ๋‹ค ์œ ํ˜• ๊ฐ€๋“œ๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

@lifaon74 , ๋‚ด๊ฐ€ ์•„๋Š” ํ•œ ์ด ๋ฌธ์ œ์— ๋Œ€ํ•œ ์›€์ง์ž„์ด ์—†์Šต๋‹ˆ๋‹ค. ์—ฌ๋Ÿฌ ์‹œ๋‚˜๋ฆฌ์˜ค๊ฐ€ ์ œ์‹œ๋˜๊ณ  ์ด๋กœ ์ธํ•ด Typescript์—์„œ ์ ์ ˆํ•˜๊ฒŒ ์„ค๋ช…ํ•  ์ˆ˜ ์—†๋Š” ์ˆ˜๋งŽ์€ ๋ ˆ๊ฑฐ์‹œ JS ์ฝ”๋“œ๊ฐ€ ์ œ์‹œ๋˜์—ˆ์ง€๋งŒ ๋ฌธ์ œ๋Š” ์ข…๊ฒฐ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ํ˜„์žฅ์˜ ์‚ฌ์‹ค์ด ๋‹ฌ๋ผ์กŒ๋‹ค๊ณ  ์ƒ๊ฐํ•œ๋‹ค๋ฉด ์ƒˆ๋กœ์šด ์‚ฌ์‹ค์„ ์—ฌ๋Š” ๊ฒƒ์ด ์ข‹์„๊นŒ์š”? ๋‚˜๋Š” ์˜ค๋ž˜๋œ ์ฃผ์žฅ์„ ๋‹ค์‹œ ์ฝ๋Š” ๊ฒƒ์— ๋Œ€ํ•œ ํŒ€์˜ ์ •์ฑ…์„ ๋ชจ๋ฅด์ง€๋งŒ ๋‚˜๋Š” ๋‹น์‹ ์˜ ๋“ฑ์„ ๋ฐ›๊ฒ ์Šต๋‹ˆ๋‹ค.

๋‚˜๋Š” ์˜ค๋ž˜๋œ ์ฃผ์žฅ์„ ๋‹ค์‹œ ์ฝ๋Š” ๊ฒƒ์— ๋Œ€ํ•œ ํŒ€์˜ ์ •์ฑ…์„ ๋ชจ๋ฅด์ง€๋งŒ ๋‚˜๋Š” ๋‹น์‹ ์˜ ๋“ฑ์„ ๋ฐ›๊ฒ ์Šต๋‹ˆ๋‹ค.

๊ทธ๋“ค์€ ์ด์ „์— ๋‹ซํžŒ ์ฃผ์ œ๋ฅผ ์žฌ๊ณ ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด์Šˆ ์ƒ๋‹จ์— ๐Ÿ‘๋ฅผ ๋ถ™์ด๋ฉด ์˜๋ฏธ๊ฐ€ ์žˆ๋‹ค๋Š” ๋ฏฟ์Œ์„ ์ค๋‹ˆ๋‹ค. ๋‚˜๋Š” ๊ทธ๊ฒƒ์ด ์ผ๋ฐ˜์ ์œผ๋กœ ์œ ํ˜• ์‹œ์Šคํ…œ์ด ๋ชจ๋“  ์ฝ๊ธฐ ๋ฐ ์“ฐ๊ธฐ์—์„œ ๋ถ„๊ธฐ๋˜์–ด์•ผ ํ•จ์„ ์˜๋ฏธํ•˜๊ธฐ ๋•Œ๋ฌธ์— "๋„ˆ๋ฌด ๋ณต์žกํ•œ" ๋ฒ”์ฃผ์— ์†ํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ์œ ํšจํ•˜์ง€๋งŒ ๋‹ค์†Œ ๋“œ๋ฌธ ์‚ฌ์šฉ ์‚ฌ๋ก€๋Š” ๊ทธ๋งŒํ•œ ๊ฐ€์น˜๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.

๋‚ด ๊ฐœ์ธ์ ์ธ ๋Š๋‚Œ์€ ํŠนํžˆ ์ด ํŒจํ„ด์„ ํšจ๊ณผ์ ์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ๊ธฐ์กด JavaScript ์ฝ”๋“œ๋ฅผ ๋ชจ๋ธ๋งํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์—์„œ _์žˆ์œผ๋ฉด ์ข‹์€_ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ €๋Š” ๊ฐœ์ธ์ ์œผ๋กœ ๋ ˆ๊ฑฐ์‹œ JS ๋ฌธ์ œ์— ๋Œ€ํ•ด ์ „ํ˜€ ๋ถ€๋‹ด์Šค๋Ÿฝ์ง€ ์•Š์€ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์„ ์ƒ๊ฐํ•ด ๋‚ธ๋‹ค๋ฉด ๋ฌธ์ œ๊ฐ€ ํ•ด๊ฒฐ๋œ ๊ฒƒ์œผ๋กœ ๊ฐ„์ฃผํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋‚˜๋Š” ์—ฌ์ „ํžˆ ์ผ์ข…์˜ TS Greenhorn์ด๋ฏ€๋กœ ํ˜„์žฌ ์†”๋ฃจ์…˜(๊ฐ•์ œ ์บ์ŠคํŒ… ๋˜๋Š” ๋ถˆํ•„์š”ํ•œ ์œ ํ˜• ๊ฐ€๋“œ)์ด ๊ธฐ์กด ๊ธฐ๋Šฅ์„ ์ตœ์ ์œผ๋กœ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ๊ฒƒ์ผ๊นŒ์š”?

๋™์˜ํ•˜๋‹ค. setter ์œ ํ˜•์ด ๊ฐ™์•„์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ ๋„ˆ๋ฌด ์ œํ•œ์ ์ž…๋‹ˆ๋‹ค... ๊ฐœ์„ ํ•˜์‹ญ์‹œ์˜ค.

์ด๋ฅผ ์ˆ˜ํ–‰ํ•˜๊ธฐ ์œ„ํ•œ ๊ถŒ์žฅ ์‚ฌํ•ญ์„ ์ฐพ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

get price() {
    return (this._price as number);
  }

  set price(price) {
    this._price = typeof price === 'string' ? parseFloat(parseFloat(price).toFixed(8)) : parseFloat(price.toFixed(8));
  }

์ €์žฅ๋œ ๊ฐ’์ด ์ˆซ์ž๊ฐ€ ๋˜๊ธฐ๋ฅผ ์›ํ•˜์ง€๋งŒ ์†์„ฑ์„ ์„ค์ •ํ•  ๋•Œ๋งˆ๋‹ค parseFloat๋ฅผ ์ˆ˜ํ–‰ํ•  ํ•„์š”๊ฐ€ ์—†๋„๋ก setter์—์„œ ๋ฌธ์ž์—ด์—์„œ float๋กœ ๋ณ€ํ™˜ํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค.

๋‚˜๋Š” ์ด๊ฒƒ์ด Typescript ๋‚ด๋ถ€์— ์ž˜ ๋งž์ง€ ์•Š๋Š” ์œ ํšจํ•œ(๋˜๋Š” ์ตœ์†Œํ•œ ํ•ฉ๋ฆฌ์ ์œผ๋กœ ์ž˜ ๋ฐ›์•„๋“ค์—ฌ์ง„) Javascript ํŒจํ„ด์ด๋ผ๊ณ  ํ‰๊ฒฐ์„ ๋‚ด๋ ธ์Šต๋‹ˆ๋‹ค. ๋‚ด๋ถ€ ๋ณ€๊ฒฝ์ด ๋„ˆ๋ฌด ํฐ ๋ณ€๊ฒฝ์ด๋ผ๋ฉด TS๊ฐ€ ๋‚ด๋ถ€์ ์œผ๋กœ ์ปดํŒŒ์ผ๋˜๋Š” ๋ฐฉ์‹์„ ๋ณ€๊ฒฝํ•˜๋Š” ์ผ์ข…์˜ ์ฃผ์„์„ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ? ๊ฐ™์€ ๊ฒƒ

class Widget {
  get price(): number | /** <strong i="7">@impossible</strong> */ string | undefined { return this._price; }
  set price(val: number|string|undefined){ ... }
}

let w = new Widget();
w.price = 10;
// Annotation processes as "let p:number|undefined = (w.price as number|undefined)"
let p: number|undefined = w.price;

์ฆ‰, TS๊ฐ€ JS๋กœ ๋ณ€ํ™˜๋˜๊ธฐ ์ „์— ์ „์ฒ˜๋ฆฌ๊ธฐ(?)๊ฐ€ w.price ์˜ ๋ชจ๋“  ์ฝ๊ธฐ๋ฅผ ๋ช…์‹œ์  ์บ์ŠคํŠธ๋กœ ๋ณ€ํ™˜ํ•˜๋„๋ก TS๋ฅผ ๋งˆํฌ์—…ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฌผ๋ก  TS๊ฐ€ ์ฃผ์„์„ ๊ด€๋ฆฌํ•˜๋Š” ๋ฐฉ๋ฒ•์˜ ๋‚ด๋ถ€๋ฅผ ์•Œ์ง€ ๋ชปํ•˜๋ฏ€๋กœ ์ด๊ฒƒ์€ ์™„์ „ํžˆ ์“ฐ๋ ˆ๊ธฐ์ผ ์ˆ˜ ์žˆ์ง€๋งŒ ์ผ๋ฐ˜์ ์ธ ์•„์ด๋””์–ด๋Š” TS ๋ณ€ํ™˜๊ธฐ๋ฅผ JS๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

์ด ๊ธฐ๋Šฅ์ด ํ•„์š”ํ•˜์ง€ ์•Š๋‹ค๋Š” ๊ฒƒ์€ ์•„๋‹ˆ์ง€๋งŒ set ๋ฅผ ์šฐํšŒํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ์žˆ์Šต๋‹ˆ๋‹ค. IMO get ๋Š” ํ•ญ์ƒ ๋™์ผํ•œ ๋ณ€์ˆ˜ ์œ ํ˜•์„ ๋ฐ˜ํ™˜ํ•ด์•ผ ํ•˜๋ฏ€๋กœ ์ด ์ •๋„๋ฉด ์ถฉ๋ถ„ํ–ˆ์Šต๋‹ˆ๋‹ค.

class Widget {
    get price(): number { return this._price; }
    set price(val){ return this.setPrice(val); } // call another function

    // do processing here
    private setPrice(price: number | string): number {
        let num = Number(price);
        return isNaN(num) ? 0 : num;
    }
}

@iamjoyce widget.price = '123' ๋Š” ์ฝ”๋“œ์—์„œ ์ปดํŒŒ์ผ ์˜ค๋ฅ˜๋ฅผ ๋ฐœ์ƒ์‹œํ‚ต๋‹ˆ๋‹ค.

@iamjoyce => ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ $ set price(val) val: number ๋ฅผ ๊ฐ€์ •ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ž˜๋ชป๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

์˜ˆ, Angular์˜ ๊ตฌ์„ฑ ์š”์†Œ ์‚ฌ์šฉ์ด ๋‹ค๋ฅธ getter/setter ์œ ํ˜•์„ ๊ฐ–๊ธฐ๋ฅผ ์›ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ €๋„ ์—ฌ๊ธฐ์— ์žˆ์Šต๋‹ˆ๋‹ค.

Angular๋Š” ์ž…๋ ฅ ์†์„ฑ์˜ ์œ ํ˜•์— ๊ด€๊ณ„์—†์ด (๋ฐ”์ธ๋”ฉ ํ‘œํ˜„์‹์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ํ•œ) ๋งˆํฌ์—…์—์„œ ๊ตฌ์„ฑ ์š”์†Œ ์†์„ฑ์„ ์„ค์ •ํ•˜๋ฉด(์†์„ฑ์„ ํ†ตํ•ด) ํ•ญ์ƒ ๋ฌธ์ž์—ด์„ ์ฃผ์ž…ํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋ชจ๋ธ๋งํ•  ์ˆ˜ ์žˆ๋‹ค๋ฉด ์ •๋ง ์ข‹์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

private _someProperty: SomeEnum;
set someProperty(value: SomeEnum | string) {
   this._someProperty = this.coerceSomeEnum(value);
} 
get someProperty(): SomeEnum {
  return this._someProperty;
}

์˜ค๋Š˜๋‚  ์ด๊ฒƒ์€ | string ๋ฅผ ์ƒ๋žตํ•˜๋ฉด ์ž‘๋™ํ•˜์ง€๋งŒ Angular๊ฐ€ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋” ์ •ํ™•ํ•˜๊ฒŒ ์„ค๋ช…ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ฝ”๋“œ์—์„œ ์•ก์„ธ์Šคํ•˜๋ฉด ์†์„ฑ์˜ ์œ ํ˜•์ด ์ค‘์š”ํ•˜์ง€๋งŒ ์†์„ฑ์ฒ˜๋Ÿผ ์„ค์ •ํ•˜๋ฉด ๋ฌธ์ž์—ด์ด ๊ฐ•์ œ๋กœ ์ž…๋ ฅ๋ฉ๋‹ˆ๋‹ค.

์šฐ๋ฆฌ๋Š” ์ด๋Ÿฐ ๋ฐฉ์‹์œผ๋กœ API๋ฅผ ์„ค๊ณ„ํ•˜๊ณ  ์‹ถ๊ธฐ ๋•Œ๋ฌธ์— ์ผ๋ฐ˜์ ์œผ๋กœ ์ด ๊ธฐ๋Šฅ์„ ์›ํ•˜์ง€ ์•Š๋Š”๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ๋‚˜๋Š” ์†์„ฑ์ด ๋ฎ๊ฐœ ์•„๋ž˜์—์„œ ๊ฐ•์ œ ๋ถ€์ž‘์šฉ์„ ์ผ์œผํ‚ค์ง€ ์•Š๋Š” ๊ฒฝ์šฐ ๋” ๋‚ซ๋‹ค๋Š” ๋ฐ ๋™์˜ํ•ฉ๋‹ˆ๋‹ค. ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋ ค๋ฉด ์†์„ฑ ์ง‘ํ•ฉ ๋Œ€ ๋ฐ”์ธ๋”ฉ ์†์„ฑ ์ง‘ํ•ฉ์ด ์„œ๋กœ ๋‹ค๋ฅธ ์ง„์ž…์ ์— ๋“ค์–ด๊ฐ€๋„๋ก Angular๊ฐ€ ์„ค๊ณ„๋˜์—ˆ์œผ๋ฉด ์ข‹์•˜์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ ์ด๊ฒƒ์„ ์‹ค์šฉ์ ์œผ๋กœ ๋ณด๋ฉด TypeScript๊ฐ€ ์ฝ๊ธฐ/์“ฐ๊ธฐ ์œ ํ˜• ํ‰๋“ฑ ๊ณต๋ฆฌ๋ฅผ ๋ฌด์‹œํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ์šฐ๋ฆฌ ์œ ํ˜•์„ ์‚ฌ์šฉํ•˜๋Š” ์™ธ๋ถ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์™€์˜ ์ƒํ˜ธ ์ž‘์šฉ์„ ๋ชจ๋ธ๋งํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค€๋‹ค๋ฉด ๋„์›€์ด ๋ฉ๋‹ˆ๋‹ค.

์ด ๊ฒฝ์šฐ ๋ชจ๋“  ์ข…๋ฅ˜์˜ ์„ฑ๊ฐ€์‹  ์œ ํ˜• ๊ฐ€๋“œ/์–ด์„ค์…˜์ด ํ•„์š”ํ•˜๋ฏ€๋กœ getter์—์„œ ๊ณต์šฉ์ฒด ์œ ํ˜•์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์€ ๋งค์šฐ ๋ฌธ์ œ๊ฐ€ ๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์–ด๋–ค ๋„๊ตฌ๋ผ๋„ ์†์„ฑ์—์„œ ์„ค์ •๋˜๋Š” ์†์„ฑ์ด ๋ฌธ์ž์—ด์—์„œ ํ• ๋‹น ๊ฐ€๋Šฅํ•ด์•ผ ํ•˜๋Š”์ง€ ํ™•์ธํ•˜๋ ค๊ณ  ์‹œ๋„ํ•˜๊ธฐ ์‹œ์ž‘ํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— setter์—์„œ ๊ณต์šฉ์ฒด ์œ ํ˜•์„ ๋‚จ๊ฒจ๋‘๋Š” ๊ฒƒ์€ ์ž˜๋ชป๋œ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ ์ด ๊ฒฝ์šฐ ์œ ํ˜• ์‹œ์Šคํ…œ์€ ์™ธ๋ถ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ์œ ํ˜•์„ ์‚ฌ์šฉํ•˜๋„๋ก ํ—ˆ์šฉ๋˜๋Š” ๋ฐฉ๋ฒ•์„ ์บก์ฒ˜ํ•  ๋งŒํผ ์ถฉ๋ถ„ํžˆ ํ‘œํ˜„์ ์ด์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ์™ธ๋ถ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ์‹ค์ œ๋กœ ์œ ํ˜• ์ •๋ณด์™€ ํ•จ๊ป˜ ์œ ํ˜• ์Šคํฌ๋ฆฝํŠธ ์ˆ˜์ค€์—์„œ ์ด๋Ÿฌํ•œ ์œ ํ˜•์„ ์†Œ๋น„ํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— _์ฆ‰๊ฐ์ ์œผ๋กœ_ ์ค‘์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๋„๊ตฌ๊ฐ€ ์œ ํ˜• ์ •๋ณด๋ฅผ ๋งค์šฐ ์ž˜ ์†Œ๋น„ํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ๊ฒฐ๊ตญ ์ค‘์š”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์œ„์˜ ํ•œ ์‚ฌ๋žŒ์€ ์•ฝ๊ฐ„ ๋ถˆ์พŒํ•ด ๋ณด์ด์ง€๋งŒ ์•„๋งˆ๋„ ์ž‘๋™ํ•  ์ˆ˜ ์žˆ๋Š” ๋Œ€์ฒด ์†”๋ฃจ์…˜์„ ์–ธ๊ธ‰ํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด setter/getter ๋ชจ๋‘์— ๋Œ€ํ•ด ๊ณต์šฉ์ฒด ์œ ํ˜•์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ๊ณต์šฉ์ฒด์˜ ํŠน์ • ์œ ํ˜•์ด getter์— ๋Œ€ํ•ด ๋ถˆ๊ฐ€๋Šฅํ•˜๋‹ค๋Š” ๊ฒƒ์„ ๋‚˜ํƒ€๋‚ด๋Š” ๋ฐฉ๋ฒ•์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์‹ค์ œ๋กœ ๋ˆ„๊ตฐ๊ฐ€๊ฐ€ ์œ ํ˜• ๊ฐ€๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์กด์žฌํ•˜์ง€ ์•Š๋Š”์ง€ ํ™•์ธํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ getter ํ˜ธ์ถœ ์‚ฌ์ดํŠธ ์‚ฌ์ดํŠธ ์ œ์–ด ํ๋ฆ„์—์„œ ๊ณ ๋ ค ์‚ฌํ•ญ์—์„œ ์‚ฌ์ „ ์ œ๊ฑฐ๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ getter์˜ ํ•˜์œ„ ์ง‘ํ•ฉ ํ•ฉ์ง‘ํ•ฉ๊ณผ ๋น„๊ตํ•˜์—ฌ setter์˜ ์ƒ์œ„ ์ง‘ํ•ฉ ํ•ฉ์ง‘ํ•ฉ์„ ํ—ˆ์šฉํ•˜๋Š” ๊ฒƒ๊ณผ ๋น„๊ตํ•˜๋ฉด ์„ฑ๊ฐ€์‹  ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ ์•„๋งˆ๋„ ๊ทธ๊ฒƒ์ด ๋‚ด๋ถ€์ ์œผ๋กœ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ๋ฐฉ๋ฒ•์ผ ๊ฒƒ์ž…๋‹ˆ๋‹ค. setter๊ฐ€ getter ์œ ํ˜•์˜ ์ƒ์œ„ ์ง‘ํ•ฉ ์กฐํ•ฉ์ธ ํ•œ. getter ๋ฐ setter ์œ ํ˜•์„ ๋‚ด๋ถ€์ ์œผ๋กœ ๋™๋“ฑํ•˜๊ฒŒ ์ทจ๊ธ‰ํ•˜์ง€๋งŒ getter์˜ ๊ณต์šฉ์ฒด ์œ ํ˜• ๋ถ€๋ถ„์„ ๋ถˆ๊ฐ€๋Šฅํ•œ ๊ฒƒ์œผ๋กœ ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์ œ์–ด ํ๋ฆ„ ๋ถ„์„์€ ๊ณ ๋ ค ์‚ฌํ•ญ์—์„œ ์ œ๊ฑฐํ•ฉ๋‹ˆ๋‹ค. ์„ค๊ณ„ ์ œ์•ฝ์„ ํ”ผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?

์œ„์˜ ๋‚ด์šฉ์„ ์ž์„ธํžˆ ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค. ๋ณตํ•ฉํ˜•์˜ ์ผ๋ถ€๋ฅผ ๋ถˆ๊ฐ€๋Šฅํ•œ ๊ฒƒ์œผ๋กœ ํ‘œ์‹œํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ด ํƒ€์ž… ํ‘œํ˜„์„ฑ์˜ ๊ด€์ ์—์„œ ์œ ์šฉํ•œ ๊ฒƒ์ผ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ๊ตฌ์กฐ๊ฐ€ ๋™์ผํ•˜์ง€๋งŒ ๋ถˆ๊ฐ€๋Šฅํ•œ ์ˆ˜์ •์ž๊ฐ€ ์—†๋Š” ๋‹ค๋ฅธ ์œ ํ˜•๊ณผ์˜ ๋™๋“ฑ์„ฑ์— ์˜ํ–ฅ์„ ๋ฏธ์น˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋ถˆ๊ฐ€๋Šฅํ•œ ์ˆ˜์ •์ž๋Š” ์ œ์–ด ํ๋ฆ„ ๋ถ„์„์—๋งŒ ์˜ํ–ฅ์„ ๋ฏธ์นฉ๋‹ˆ๋‹ค.

๋Œ€์ฒด ์ œ์•ˆ์œผ๋กœ ์‚ฌ์šฉ์ž ์ •์˜ ์œ ํ˜• ๊ฐ€๋“œ๋ฅผ ๋ฐ˜ํ™˜ ๊ฐ’์— ์ ์šฉํ•˜๋Š” ๊ตฌ๋ฌธ์ด ์žˆ๋‹ค๋ฉด ์ด๊ฒƒ์œผ๋กœ๋„ ์ถฉ๋ถ„ํ•ฉ๋‹ˆ๋‹ค. ์ •์ƒ์ ์ธ ์ƒํ™ฉ์—์„œ๋Š” ์ด๊ฒƒ์ด ์•ฝ๊ฐ„ ์šฐ์Šค๊ฝ์Šค๋Ÿฝ์ง€๋งŒ ๋ฐ˜ํ™˜ ๊ฐ’๊ณผ ์ธ์ˆ˜์— ๋Œ€ํ•ด ๊ทธ๋Ÿฐ ์ข…๋ฅ˜์˜ ํ‘œํ˜„์ด ์žˆ์œผ๋ฉด ์ด๋Ÿฌํ•œ ๊ทน๋‹จ์ ์ธ ๊ฒฝ์šฐ๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๋ฐ˜ํ™˜ ๊ฐ’์— ๋Œ€ํ•œ ์‚ฌ์šฉ์ž ์ •์˜ ์œ ํ˜• ๋ณดํ˜ธ๋Š” ์†์„ฑ์œผ๋กœ ์••์ถ•๋  ๋•Œ ์œ ํ˜• ์„ ์–ธ/์ธํ„ฐํŽ˜์ด์Šค์—์„œ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ๋Š” ์ด์ ๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

์—ฌ๊ธฐ์— ๋‹ค๋ฅธ ์‚ฌ์šฉ ์‚ฌ๋ก€๋ฅผ ์ถ”๊ฐ€ํ•˜๊ธฐ๋งŒ ํ•˜๋ฉด mobx-state-tree๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ช‡ ๊ฐ€์ง€ ๋‹ค๋ฅธ ๋ฐฉ๋ฒ•(์ธ์Šคํ„ด์Šค ๋ฐ ์Šค๋ƒ…์ƒท ์œ ํ˜•์—์„œ)์œผ๋กœ ์†์„ฑ์„ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ get ์ ‘๊ทผ์ž์—์„œ ๋‹จ์ผ ํ‘œ์ค€ ๋ฐฉ์‹(์ธ์Šคํ„ด์Šค)์œผ๋กœ๋งŒ ์†์„ฑ์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ์ง€์›๋œ๋‹ค๋ฉด ๋งค์šฐ ์œ ์šฉํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๋‚˜๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ณ  ์žˆ๋‹ค.

interface SomeNestedString {
  foo: string;
}

...

private _foo: SomeNestedString | string;

get foo(): SomeNestedString | string {
  return this._foo;
}

set foo(value: SomeNestedString | string) {
  this._foo = (value as SomeNestedString).foo;
}

๋‚˜๋Š” ๊ทธ๊ฒƒ์ด ๋‹น๋ฉดํ•œ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์‹ค์ œ๋กœ๋Š” getter๊ฐ€ ๊ณต์šฉ์ฒด ์œ ํ˜•์˜ ํ•˜์œ„ ์ง‘ํ•ฉ๋งŒ ๋ฐ˜ํ™˜ํ•˜๋”๋ผ๋„ getter๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ ์—ฌ์ „ํžˆ ์œ ํ˜• ๊ฐ€๋“œ๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

TSLint๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด any ๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ปดํŒŒ์ผ๋Ÿฌ๋„ ๋ถˆํ‰ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

export class FooBar {
  private bar: string;

  get foo (): string | any {
    return this.bar;
  }

  set foo (value: Date | string | any) {
    // Type guarding enables IntelliSense in VS Code
    if (value instanceof Date) {
      this.bar = value.toISOString();
    } else if (typeof value === 'string') {
      this.bar = value;
    } else {
      this.bar = String(value); // Or throw an error
    }
  }
}

@jpidelatorre ์ด๋Ÿฐ ์‹์œผ๋กœ ์œ ํ˜• ์•ˆ์ „์„ฑ์„ ์žƒ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

const fooBar = new FooBar()
const a: number = fooBar.foo // works while it should fail
fooBar.foo = 123 // fails only at runtime, not compile time. It doesnt fail in this particular case with strings and numbers, but it will with something more complex

@keenondrums ์ด๊ฒƒ์ด ๋ฐ”๋กœ ์šฐ๋ฆฌ๊ฐ€ ์ ‘๊ทผ์ž๊ฐ€ ๋‹ค๋ฅธ ์œ ํ˜•์„ ๊ฐ€์ง€๊ธฐ๋ฅผ ์›ํ•˜๋Š” ์ด์œ ์ž…๋‹ˆ๋‹ค. ๋‚ด๊ฐ€ ์ฐพ์€ ๊ฒƒ์€ ํ•ด๊ฒฐ์ฑ…์ด ์•„๋‹ˆ๋ผ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค.

@jpidelatorre ํ˜„์žฌ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์€ ๋‹ค๋ฅธ ๊ธฐ๋Šฅ์„ setter๋กœ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

export class FooBar {
  private bar: string;

  get foo (): string {
    return this.bar;
  }

  setFoo (value: Date | string ) {}
}

@keenondrums ์ ‘์†์ž๋งŒํผ์€ ์•„๋‹ˆ์ง€๋งŒ ์•„์ง๊นŒ์ง€๋Š” ์ตœ์„ ์˜ ์„ ํƒ์ž…๋‹ˆ๋‹ค.

getter์— ๋Œ€ํ•ด ๋ณ„๋„์˜ ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ํ•œ Angular ๊ตฌ์„ฑ ์š”์†Œ์˜ @input ์†์„ฑ์œผ๋กœ ๋ฐœ์ƒํ•˜๋Š” ์ผ์— ๋Œ€ํ•œ ๋ชจ๋ธ์ด ์•„๋‹™๋‹ˆ๋‹ค.

๋„ˆ๋ฌด ์ถ”์•…ํ•ฉ๋‹ˆ๋‹ค.

๋‚˜๋Š” ๋˜ํ•œ ์ด ๊ธฐ๋Šฅ์„ ์›ํ•˜์ง€๋งŒ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์ด ์—†๋Š” .d.ts ํŒŒ์ผ์—์„œ ์ž˜ ์ž‘๋™ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. Mocha(Objective-C/Javascript ๋ธŒ๋ฆฌ์ง€)๋ฅผ ํ†ตํ•ด ๋…ธ์ถœ๋œ ์ผ๋ถ€ ํด๋ž˜์Šค๋ฅผ ๋ฌธ์„œํ™”ํ•˜๋ ค๊ณ  ํ•˜๊ณ  ๋ž˜ํ•‘๋œ ํ•ญ๋ชฉ์˜ ์ธ์Šคํ„ด์Šค ์†์„ฑ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์„ค์ •๋ฉ๋‹ˆ๋‹ค.

class Foo {
    get bar:()=>number;
    set bar:number;
}

const foo = new Foo();
foo.bar = 3;
foo.bar(); // 3

๋˜ํ•œ API๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ธํ„ฐํŽ˜์ด์Šค์™€ ์ผ์น˜ํ•˜๋Š” ๊ฐ์ฒด๋กœ ์†์„ฑ์„ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ getter๋Š” ํ•ญ์ƒ ์‹ค์ œ ํด๋ž˜์Šค ์ธ์Šคํ„ด์Šค๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฒฝ์šฐ๋ฅผ ๋งŽ์ด ๋ณด์•˜์Šต๋‹ˆ๋‹ค.

interface IFoo {
    bar: string;
}

class Foo implements IFoo {
    bar: string;
    toString():string;
}

class Example {
    get foo:Foo;
    set foo:Foo|IFoo;
}

๋‚˜๋Š” ์ด ๋ฌธ์ œ์— ๋Œ€ํ•ด ๋Œ€์ฒด๋กœ ์žŠ๊ณ  ์žˆ์—ˆ์ง€๋งŒ, ๊ทธ๊ฒƒ์„ ๋‹ค์‹œ ์ฝ์œผ๋ฉด์„œ ํ•œ ๊ฐ€์ง€ ์ƒ๊ฐ์ด ๋– ์˜ฌ๋ž๋‹ค. ๋‚˜๋Š” ์ด๊ฒƒ์ด ์ถ”์ƒ์ ์œผ๋กœ ํ•  ๊ฐ€์น˜๊ฐ€ ์žˆ์ง€๋งŒ ์‹คํ˜„ ๊ฐ€๋Šฅํ•˜๊ธฐ์—๋Š” ๋„ˆ๋ฌด ๊ธฐ์ˆ ์ ์œผ๋กœ ๋ณต์žกํ•˜๋‹ค๋Š” ์•„์ด๋””์–ด์— ์ •์ฐฉํ–ˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๊ฒƒ์€ ์ ˆ์ถฉ์  ๊ณ„์‚ฐ์ž…๋‹ˆ๋‹ค. ๊ธฐ์ˆ ์ ์œผ๋กœ ๋ถˆ๊ฐ€๋Šฅํ•œ ๊ฒƒ์€ ์•„๋‹ˆ๋ฉฐ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐ ์‹œ๊ฐ„๊ณผ ๋…ธ๋ ฅ(๋ฐ ์ฝ”๋“œ ๋ณต์žก์„ฑ ์ถ”๊ฐ€)์˜ ๊ฐ€์น˜๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ์˜ค๋ฅธ์ชฝ?

์ด๊ฒƒ์ด ํ•ต์‹ฌ DOM API๋ฅผ ์ •ํ™•ํ•˜๊ฒŒ ๊ธฐ์ˆ ํ•˜๋Š” ๊ฒƒ์„ ๋ถˆ๊ฐ€๋Šฅํ•˜๊ฒŒ ๋งŒ๋“ ๋‹ค๋Š” ์‚ฌ์‹ค์ด ์ˆ˜ํ•™์„ ์ „ํ˜€ ๋ณ€๊ฒฝํ•ฉ๋‹ˆ๊นŒ? @RyanCavanaugh ๋ผ๊ณ 

๋‚˜๋Š” ์ด ์ฝ”๋“œ foo.bar = "hello"; console.log(foo.bar); ๊ฐ€ ์ •์ƒ์ ์ธ ์˜๋ฏธ๋ฅผ ๊ฐ€์ง€๋ ค๊ณ  ์‹œ๋„ํ•˜๋Š” ์–ธ์–ด์—์„œ "hello" ์ด์™ธ์˜ ๋ชจ๋“  ๊ฒƒ์„ ์ธ์‡„ํ•ด์•ผ ํ•œ๋‹ค๋Š” ์ƒ๊ฐ์— ์ง„์ •์œผ๋กœ ๋ฐ˜๋Œ€ํ•ฉ๋‹ˆ๋‹ค.

์ด๋Ÿฐ ์‹์œผ๋กœ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋Š”์ง€์— ๋Œ€ํ•ด ๋…ผ์Ÿํ•  ์ˆ˜ ์žˆ์ง€๋งŒ DOM์€ ํ•ญ์ƒ el.hidden=1; console.log(el.hidden) // <-- true, not 1 ์™€ ๊ฐ™์€ ๊ตฌ์„ฑ์„ ์ง€์›ํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ๋‹จ์ง€ ์†Œ์ˆ˜์˜ ์‚ฌ๋žŒ๋“ค์ด ์‚ฌ์šฉํ•˜๋Š” ํŒจํ„ด์ด ์•„๋‹ˆ๋ฉฐ ์ธ๊ธฐ ์žˆ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์— ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์ง€์›ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. JS๊ฐ€ ํ•ญ์ƒ ์–ด๋–ป๊ฒŒ ์ž‘๋™ํ–ˆ๋Š”์ง€์— ๋Œ€ํ•œ ํ•ต์‹ฌ ๊ต๋ฆฌ์ž…๋‹ˆ๋‹ค. DWIM์ด ์–ธ์–ด์˜ ํ•ต์‹ฌ์— ๋…น์•„๋“ค์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ์–ธ์–ด ์ˆ˜์ค€์—์„œ ์ด๋ฅผ ๋ถˆ๊ฐ€๋Šฅํ•˜๊ฒŒ ๋งŒ๋“œ๋Š” ๊ฒƒ์€ JS์˜ "์ƒ์œ„ ์ง‘ํ•ฉ"์ด์–ด์•ผ ํ•œ๋‹ค๋Š” TS์˜ ๊ธฐ๋ณธ ์›์น™์„ ๊นจ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. . ๊ทธ๊ฒƒ์€ ๋ฒค๋‹ค์ด์–ด๊ทธ๋žจ์—์„œ ํŠ€์–ด๋‚˜์˜จ ๋ชป์ƒ๊ธด ๊ฑฐํ’ˆ์ด๋ฉฐ, ์šฐ๋ฆฌ๋Š” ๊ทธ๊ฒƒ์„ ์žŠ์–ด์„œ๋Š” ์•ˆ๋ฉ๋‹ˆ๋‹ค.

์ด๊ฒƒ์ด ๋‚ด๊ฐ€ ์—ฌ์ „ํžˆ ๋™์ผํ•œ ์œ ํ˜•์˜ setter/getter๋ฅผ ์œ ์ง€ํ•˜๋Š” ์•„์ด๋””์–ด๋ฅผ ์ข‹์•„ํ•˜๋Š” ์ด์œ ์ž…๋‹ˆ๋‹ค.

number | boolean

๊ทธ๋Ÿฌ๋‚˜ getter๊ฐ€ ๊ธฐ์ˆ ์ ์œผ๋กœ ๋™์ผํ•œ ๊ณต์šฉ์ฒด ์œ ํ˜•์„ ๊ฐ–์ง€๋งŒ ์‹ค์ œ๋กœ๋Š” ๊ณต์šฉ์ฒด์— ์žˆ๋Š” ์œ ํ˜•์˜ ํ•˜์œ„ ์ง‘ํ•ฉ๋งŒ ๋ฐ˜ํ™˜ํ•œ๋‹ค๋Š” ๊ฒƒ์„ ๋‚˜ํƒ€๋‚ผ ์ˆ˜ ์žˆ๋Š” ์ผ์ข…์˜ typegaurd๋ฅผ ๋„์ž…ํ•ฉ๋‹ˆ๋‹ค. getter(์ถ”๋ก  ํ๋ฆ„ ๋ฌธ์ œ?)์—์„œ ์ผ์ข…์˜ ์ขํžˆ๋Š” ๊ฐ€๋“œ๋กœ ์ฒ˜๋ฆฌํ•˜๋ฉด ์œ ํ˜• ๋ชจ๋ธ์„ ์ˆ˜์ •ํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค ๋” ๊ฐ„๋‹จํ•ด์ง€์ง€ ์•Š์Šต๋‹ˆ๊นŒ? (๊ทธ๋Š” ๋‚ด๋ถ€์— ๋Œ€ํ•ด ์•„๋ฌด๊ฒƒ๋„ ๋ชจ๋ฅธ๋‹ค๊ณ  ๋งํ•œ๋‹ค...)

๋˜๋Š” getter์— ์‚ฌ์šฉ๋œ ์œ ํ˜•์ด setters ์œ ํ˜•์˜ ์—„๊ฒฉํ•œ ํ•˜์œ„ ์ง‘ํ•ฉ์ธ ๊ฒฝ์šฐ์—๋งŒ ์•”์‹œ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?

๋˜๋Š” getter์— ์‚ฌ์šฉ๋œ ์œ ํ˜•์ด setters ์œ ํ˜•์˜ ์—„๊ฒฉํ•œ ํ•˜์œ„ ์ง‘ํ•ฉ์ธ ๊ฒฝ์šฐ์—๋งŒ ์•”์‹œ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?

๐Ÿ‘ !

์„ค์ • ๊ฐ€๋Šฅํ•˜์ง€ ์•Š์€ ์œ ํ˜•์„ ์–ป์„ ์ˆ˜ ์—†์–ด์•ผ ํ•œ๋‹ค๋Š” ๋ฐ ์šฐ๋ฆฌ ๋ชจ๋‘ ๋™์˜ํ•  ์ˆ˜ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. get ์˜ ์œ ํ˜•์„ ์ž๋™์œผ๋กœ ์ขํž ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ•˜์—ฌ ํ•ญ์ƒ ๊ทธ๋Ÿฐ ์œ ํ˜•์ด ๋˜๋„๋ก ํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค.

๋‚˜๋Š” ์™œ ์ผ๋ถ€ ์‚ฌ๋žŒ๋“ค์ด ๊ทธ๊ฒƒ์ด ์œ ํ˜• ์•ˆ์ „๊ณผ ๋ชจ๋“  ๊ฒƒ์„ ์œ„๋ฐ˜ํ•  ๊ฒƒ์ด๋ผ๊ณ  ๋ฐ˜๋Œ€ํ•˜๋Š”์ง€ ์ดํ•ดํ•˜์ง€ ๋ชปํ•ฉ๋‹ˆ๋‹ค. ์ ์–ด๋„ setter๊ฐ€ ๋‹ค๋ฅธ ์œ ํ˜•์„ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๋„๋ก ํ—ˆ์šฉํ•˜๋Š” ๊ฒฝ์šฐ ์œ ํ˜• ์•ˆ์ „์„ฑ์„ ์œ„๋ฐ˜ํ•˜๋Š” ๊ฒƒ์œผ๋กœ ๋ณด์ด์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
์ „:
์†์„ฑ์ด Array๋ผ๊ณ  ๊ฐ€์ •ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.๊ทธ๋Ÿฌ๋‚˜ DB์—์„œ๋Š” '10,20,40'๊ณผ ๊ฐ™์ด ์‰ผํ‘œ๋กœ ๊ตฌ๋ถ„๋œ ๋ฌธ์ž์—ด๋กœ ๋ฐ˜ํ™˜๋ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ง€๊ธˆ์€ ๊ทธ๊ฒƒ์„ ๋ชจ๋“œ ์†์„ฑ์— ๋งคํ•‘ํ•  ์ˆ˜ ์—†์œผ๋ฏ€๋กœ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ํ—ˆ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค๋ฉด ๋งค์šฐ ๋„์›€์ด ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๊ฐœ์ธ _employeeIdList : ๋ฒˆํ˜ธ[]

EmployeeIDList() ๊ฐ€์ ธ์˜ค๊ธฐ: ์ˆซ์ž[] {
์ด๊ฒƒ์„ ๋ฐ˜ํ™˜ํ•˜์‹ญ์‹œ์˜ค._employeeIdList ;
}
EmployeeIDList(_idList: ๋ชจ๋“  ) ์„ค์ • {
if (typeof _idList== '๋ฌธ์ž์—ด') {
this._employeeIdList = _idList.split(',').map(d => ์ˆซ์ž(d));
}
else if (typeof _idList== '๊ฐ์ฒด') {
this._employeeIdList = _idList as number[];
}
}

๋‚˜๋Š” ์ด ๋ฌธ์ œ๋ฅผ ์‰ฝ๊ฒŒ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์—ˆ๊ณ  SET์—์„œ ๋‹ค๋ฅธ ์œ ํ˜•์„ ํ—ˆ์šฉํ–ˆ์ง€๋งŒ ์—ฌ์ „ํžˆ ์†์„ฑ์— ์ž˜๋ชป๋œ ์œ ํ˜•์„ ํ• ๋‹นํ•˜๋Š” ๊ฒƒ์„ ๋ง‰์ง€๋งŒ ์™„๋ฒฝํ•˜๊ฒŒ ์œ ํ˜• ์•ˆ์ „ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‹ˆ ์Šน๋ฆฌํ•˜์„ธ์š”. ํŒ€์›๋“ค์ด ์ž์กด์‹ฌ์„ ๋‚ด๋ ค๋†“๊ณ  ๊ทธ๊ฒƒ์ด ๋งŒ๋“ค์–ด๋‚ด๋Š” ๋ฌธ์ œ๋ฅผ ์ƒ๊ฐํ•˜๊ณ  ๊ณ ์ณ๋‚˜๊ฐ€๊ธธ ๋ฐ”๋ž๋‹ˆ๋‹ค.

๋‚˜๋Š” ์ด๊ฒƒ์ด ๊ธฐ์กด JS ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ๋™์ž‘์„ ๋ชจ๋ธ๋งํ•˜๋Š” ๋ฐ ์—ฌ์ „ํžˆ ์ค‘์š”ํ•˜๋‹ค๊ณ  ์ƒ๊ฐํ•œ๋‹ค๋Š” ์ ์—์„œ ์ฐจ์ž„ํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค.

์ฝ”๋ฅผ ์ผœ๊ณ  ์œ ํ˜•์„ ๋“ค์–ด์˜ค๋Š” ์œ ํ˜•์˜ ํ•˜์œ„ ์ง‘ํ•ฉ์œผ๋กœ ๊ฐ•์ œ ๋ณ€ํ™˜ํ•˜๊ณ  ํ•ญ์ƒ getter์˜ ํ•˜์œ„ ์ง‘ํ•ฉ์„ ์ฝ”๋“œ ๋ƒ„์ƒˆ๋กœ ๋ฐ˜ํ™˜ํ•˜๋Š” setter๋ฅผ ์ •์˜ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์ง€๋งŒ ์‹ค์ œ๋กœ๋Š” JS ์˜์—ญ์—์„œ ์ƒ๋‹นํžˆ ์ผ๋ฐ˜์ ์ธ ํŒจํ„ด์ž…๋‹ˆ๋‹ค. .

TypeScript๋Š” ์ด์ƒ์ ์œผ๋กœ ๊ตฌ์กฐํ™”๋œ API๊ฐ€ ์—†๋Š” ๊ฒฝ์šฐ์—๋„ ๊ธฐ์กด JS API์˜ ์ƒ์ž๋ฅผ ์„ค๋ช…ํ•  ๋•Œ ๋งค์šฐ ํ‘œํ˜„๋ ฅ์ด ๋›ฐ์–ด๋‚˜๋‹ค๋Š” ์ ์—์„œ ํ›Œ๋ฅญํ•˜๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. TypeScript๊ฐ€ getter๊ฐ€ ํ•ญ์ƒ getter ์œ ํ˜•์˜ ์—„๊ฒฉํ•œ ํ•˜์œ„ ์ง‘ํ•ฉ์ธ ์œ ํ˜•์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค๋Š” ๊ฒƒ์„ ๋‚˜ํƒ€๋‚ผ ์ˆ˜ ์žˆ์„ ๋งŒํผ ํ‘œํ˜„๋ ฅ์ด ๋›ฐ์–ด๋‚˜๋ฉด ๊ธฐ์กด API ๋ชจ๋ธ๋ง์— ์—„์ฒญ๋‚œ ๊ฐ€์น˜๊ฐ€ ์ถ”๊ฐ€๋˜๋Š” ์žฅ๋ฉด์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ๋”!

์‹ ๋ขฐํ•  ์ˆ˜ ์žˆ๋Š” ์œ ํ˜• ์€ DOM XSS์™€ ์‹ธ์šฐ๊ธฐ ์œ„ํ•œ ์ƒˆ๋กœ์šด ๋ธŒ๋ผ์šฐ์ € API ์ œ์•ˆ์ž…๋‹ˆ๋‹ค. Chromium์—์„œ ์ด๋ฏธ ๊ตฌํ˜„๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค(ํ”Œ๋ž˜๊ทธ ๋’ค). API์˜ ๋Œ€๋ถ€๋ถ„์€ ์‹ ๋ขฐํ•  ์ˆ˜ ์žˆ๋Š” ์œ ํ˜•์„ ํ—ˆ์šฉํ•˜๋„๋ก ๋‹ค์–‘ํ•œ DOM ์†์„ฑ์˜ ์„ค์ •์ž๋ฅผ ์ˆ˜์ •ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด .innerHTML ๋Š” TrustedHTML | string ๋ฅผ ํ—ˆ์šฉํ•˜์ง€๋งŒ ํ•ญ์ƒ string ๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. TypeScript์—์„œ API๋ฅผ ์„ค๋ช…ํ•˜๋ ค๋ฉด ์ด ๋ฌธ์ œ๋ฅผ ์ˆ˜์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์ด์ „ ์ฃผ์„๊ณผ์˜ ์ฐจ์ด์ ์€ ์ด๊ฒƒ์€ ์‰ฝ๊ฒŒ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์—†๋Š” ๋ธŒ๋ผ์šฐ์ € API(์‚ฌ์šฉ์ž ์˜์—ญ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ์•„๋‹˜)๋ผ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋˜ํ•œ Element.innerHTML any (ํ˜„์žฌ ๊ฐ€๋Šฅํ•œ ์œ ์ผํ•œ ์†”๋ฃจ์…˜)๋กœ ๋ณ€๊ฒฝํ•˜๋Š” ์˜ํ–ฅ์€ ์‚ฌ์šฉ์ž ์˜์—ญ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ๋ถ€์ •ํ™•ํ•˜๊ฒŒ ์„ค๋ช…ํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค ํฝ๋‹ˆ๋‹ค.

์ด pull-request๊ฐ€ ๋‹ค์‹œ ์—ด๋ฆด ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ์Šต๋‹ˆ๊นŒ? ์•„๋‹ˆ๋ฉด ๋‚ด๊ฐ€ ๋†“์นœ ๋‹ค๋ฅธ ์†”๋ฃจ์…˜์ด ์žˆ์Šต๋‹ˆ๊นŒ?

์ฐธ์กฐ: @mprobst , @koto.

TypeScript์™€ ๊ฐ™์€ ์œ ํ˜• ํ†ตํ•ฉ์„ ์ง€์›ํ•˜๋Š” ์–ธ์–ด์—์„œ ์ด ๊ธฐ๋Šฅ์€ ์ž์—ฐ์Šค๋Ÿฝ๊ณ  ํŒ๋งค ํฌ์ธํŠธ์ž…๋‹ˆ๋‹ค.

@RyanCavanaugh getter์™€ setter๊ฐ€ ๊ฐ™์€ ์œ ํ˜•์„ ๊ฐ€์ง€๊ณ  ์žˆ๋”๋ผ๋„ setter๋กœ o.x === y ์ดํ›„์˜ o.x = y #$0$#$๊ฐ€ ๊ฐ’์„ ์ €์žฅํ•˜๊ธฐ ์ „์— ์ผ๋ถ€ ์ •๋ฆฌ๋ฅผ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๋ณด์žฅ์€ ์—†์Šต๋‹ˆ๋‹ค.

element.scrollTop = -100;
element.scrollTop; // returns 0

@vrana์˜ ๋‘ ๋ฒˆ์งธ ์šฐ๋ ค ์‚ฌํ•ญ์ž…๋‹ˆ๋‹ค. ํ˜„์žฌ ๋™์ž‘์œผ๋กœ ์ธํ•ด Typescript์—์„œ ๊ธฐ์กด API ์ค‘ ์ผ๋ถ€๋ฅผ ๋ชจ๋ธ๋งํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

์ด๊ฒƒ์€ setter์™€ getter ์œ ํ˜•์ด ๋‹ค๋ฅธ ๋งŽ์€ Web API์— ํŠนํžˆ ํ•ด๋‹น๋ฉ๋‹ˆ๋‹ค. ์‹ค์ œ๋กœ ์›น API ์„ค์ •์ž๋Š” ๋ชจ๋“  ์ข…๋ฅ˜์˜ ์œ ํ˜• ๊ฐ•์ œ ๋ณ€ํ™˜์„ ์ˆ˜ํ–‰ํ•˜๋ฉฐ, ๊ทธ ์ค‘ ์ผ๋ถ€๋Š” ์ฃผ์–ด์ง„ ๋ธŒ๋ผ์šฐ์ € ๊ธฐ๋Šฅ์— ๋Œ€ํ•ด ์ง์ ‘ ์ง€์ •๋˜์ง€๋งŒ ๋Œ€๋ถ€๋ถ„์€ IDL ์„ ํ†ตํ•ด ์•”์‹œ์ ์œผ๋กœ ์ˆ˜ํ–‰๋ฉ๋‹ˆ๋‹ค. ๋งŽ์€ setter๊ฐ€ ๊ฐ’๋„ ๋ณ€๊ฒฝํ•ฉ๋‹ˆ๋‹ค(์˜ˆ: ์œ„์น˜ ์ธํ„ฐํŽ˜์ด์Šค ์‚ฌ์–‘ ์ฐธ์กฐ). ์ด๊ฒƒ์€ ๋‹จ์ผ ๊ฐœ๋ฐœ์ž ์‹ค์ˆ˜๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค. ์›น ๊ฐœ๋ฐœ์ž๊ฐ€ ์ฝ”๋”ฉํ•˜๋Š” API ์‚ฌ์–‘์ž…๋‹ˆ๋‹ค.

getter ์œ ํ˜•์„ ์ขํžˆ๋ฉด Typescript๊ฐ€ ํ•ด๋‹น API๋ฅผ ๋‚˜ํƒ€๋‚ผ ์ˆ˜ ์žˆ์ง€๋งŒ ์ด์ œ๋Š” ๋ถˆ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

์†์„ฑ์˜ ์œ ํ˜•์ด setter์— ์ œ๊ณตํ•˜๊ฑฐ๋‚˜ getter์—์„œ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๋Š” ๊ฐ€๋Šฅํ•œ ์œ ํ˜•์˜ ์กฐํ•ฉ์ด๋ผ๊ณ  ๋งํ•˜๋Š” ๊ฒƒ์ด ์ •ํ™•ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ด๋Ÿฌํ•œ API๋ฅผ ๋‚˜ํƒ€๋‚ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

API๋ฅผ ๊ทธ๋Ÿฐ ์‹์œผ๋กœ ์„ค๋ช…ํ•˜๋Š” ๊ฒƒ์€ _ํšจ์œจ์ _์ด ์•„๋‹™๋‹ˆ๋‹ค. ์†Œ๋น„์ž๊ฐ€ ๊ฐ€๋Šฅํ•œ ์œ ํ˜•์„ ์ขํžˆ๊ธฐ ์œ„ํ•ด getter๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ชจ๋“  ์ธ์Šคํ„ด์Šค์—์„œ ์œ ํ˜• ๊ฐ€๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋„๋ก ์š”๊ตฌํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

๋งŽ์€ Web API๊ฐ€ ์‚ฌ์–‘์— ์ž ๊ฒจ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ํ•ญ์ƒ getter์—์„œ ์ถ•์†Œ๋œ ์œ ํ˜•์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฒƒ์„ ๊ณต๋ฆฌ์ ์œผ๋กœ ๋งŒ๋“ค์ง€ ์•Š์•˜์–ด๋„ ๊ดœ์ฐฎ์Šต๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ ๊ทธ๊ฒƒ์„ ์ž ์‹œ ์ œ์ณ๋‘๊ณ  ์‚ฌ์šฉ์ž API์— ๋Œ€ํ•ด ์ด์•ผ๊ธฐํ•˜๋”๋ผ๋„ setter ์—์„œ ๊ณต์šฉ์ฒด ์œ ํ˜•์„ ์ˆ˜๋ฝํ•˜๋Š” ๊ฐ•๋ ฅํ•œ ์‚ฌ์šฉ ์‚ฌ๋ก€๋Š” "์Šคํฌ๋ฆฝํŠธ"์ž…๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋Š” ์šฐ๋ฆฌ๊ฐ€ ์‹ค์ œ๋กœ ์›ํ•˜๋Š” ์œ ํ˜•์œผ๋กœ ์ˆ˜์šฉ ๊ฐ€๋Šฅํ•˜๊ฒŒ ๊ฐ•์ œํ•  ์ˆ˜ ์žˆ๋Š” ์ด์‚ฐ ์œ ํ˜•์˜ ๋ฒ”์œ„๋ฅผ ํ—ˆ์šฉํ•˜๊ธฐ๋ฅผ ์›ํ•ฉ๋‹ˆ๋‹ค.

์™œ ํ—ˆ์šฉํ•ฉ๋‹ˆ๊นŒ? ์‚ฌ์šฉ์˜ ์šฉ์ด์„ฑ.

์ž์ฒด ํŒ€์—์„œ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด ๋‚ด๋ถ€์ ์œผ๋กœ ๊ฐœ๋ฐœ ์ค‘์ธ API์—๋Š” ์ค‘์š”ํ•˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ์ง€๋งŒ, ๊ณต๊ฐœ๋˜๊ณ  ์ผ๋ฐ˜ํ™”๋œ ์‚ฌ์šฉ์„ ์œ„ํ•ด ์„ค๊ณ„๋œ API์—๋Š” ์ค‘์š”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

TypeScript๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ผ๋ถ€ ์†์„ฑ์— ๋Œ€ํ•ด ํ—ˆ์šฉ๋˜๋Š” ์œ ํ˜•์„ ์™„ํ™”ํ•œ API๋ฅผ ์ •ํ™•ํ•˜๊ฒŒ ์„ค๋ช…ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์€ ๋ฉ‹์ง„ ์ผ์ด์ง€๋งŒ, getter ๋ฐ˜ํ™˜ ์œ ํ˜•์„ ๊ฒฐ์ •ํ•˜๊ธฐ ์œ„ํ•ด ๊ณผ๋„ํ•œ ์œ ํ˜• ๊ฒ€์‚ฌ/๋ณดํ˜ธ๊ฐ€ ํ•„์š”ํ•œ ๋‹ค๋ฅธ ์ชฝ ๋์˜ ๋งˆ์ฐฐ๋กœ ์ธํ•ด ๊ทธ ์ด์ ์ด ์†์ƒ๋ฉ๋‹ˆ๋‹ค. , _์ง€์ •_ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.

๋‚˜๋Š” ๊ทธ๊ฒƒ์ด @RyanCavanaugh๊ฐ€ ๊ฐ€์ •ํ•˜๋Š” ์ด์ƒ์ ์ธ ๊ฒฝ์šฐ์™€ ๋‹ค๋ฅธ ์‹œ๋‚˜๋ฆฌ์˜ค๋ผ๊ณ  ์ฃผ์žฅํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค. ์ด ๊ฒฝ์šฐ๋Š” ์ง€์› ํ•„๋“œ์—๋„ ๋™์ผํ•œ ๊ณต์šฉ์ฒด ์œ ํ˜•์ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์— getter ๋ฐ setter๊ฐ€ ํ•ญ์ƒ ๋™์ผํ•œ ๊ณต์šฉ์ฒด ์œ ํ˜•์„ ๊ฐ€์ ธ์•ผ ํ•˜๋ฉฐ ํ•ญ์ƒ ํ•ด๋‹น ๊ฐ’์„ ์™•๋ณตํ•˜๊ฒŒ ๋˜๋ฉฐ ์œ ํ˜•์„ ๋ณ€๊ฒฝํ•˜๋Š” ๊ฒƒ์€ ๋ฌด์˜๋ฏธํ•˜๋‹ค๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

๋‚ด ์ƒ๊ฐ์—๋Š” ์ด ์‚ฌ๋ก€๊ฐ€ ๋” ์ด์ƒํ™”๋œ ๊ณต์šฉ์ฒด ์œ ํ˜• ์‚ฌ์šฉ์„ ์ค‘์‹ฌ์œผ๋กœ ํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ์ฆ‰, ์ƒ์„ฑ๋œ ์œ ํ˜•์„ ์ฒ˜๋ฆฌํ•˜๊ณ  ์‹ค์ œ๋กœ ํ•ด๋‹น ์—ฐํ•ฉ ์œ ํ˜•์„ ์˜๋ฏธ ๋‹จ์œ„๋กœ ์ทจ๊ธ‰ํ•˜๋ฏ€๋กœ ๋ณ„์นญ์„ ์ƒ์„ฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

type urlRep = string | Url;

๋Œ€๋ถ€๋ถ„์˜ ๊ฒƒ์€ ๊ทธ๋ƒฅ ์™•๋ณตํ•˜๊ณ  ์ผ๋ฐ˜์ ์ธ ์†Œํ’ˆ๋งŒ ๋‹ค๋ฃจ๋ฉฐ ๊ฒฝ์šฐ์— ๋”ฐ๋ผ ์ผ๋ถ€ ์œ ํ˜• ๊ฐ€๋“œ๋กœ ๋ธ”๋ž™๋ฐ•์Šค๋ฅผ ๊นจ๋œจ๋ฆด ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๋‚˜๋Š” ๊ทธ๊ฒƒ์ด ์šฐ๋ฆฌ๊ฐ€ ์—ฌ๊ธฐ์„œ ์„ค๋ช…ํ•˜๋Š” ๊ฒƒ๊ณผ๋Š” ์™„์ „ํžˆ ๋‹ค๋ฅธ ์‹œ๋‚˜๋ฆฌ์˜ค๋ผ๊ณ  ์ฃผ์žฅํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๊ฐ€ ์„ค๋ช…ํ•˜๋Š” ๊ฒƒ์€ ํŠนํžˆ JavaScript์™€ ๊ฐ™์€ ์Šคํฌ๋ฆฝํŒ… ์–ธ์–ด์—์„œ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•œ ์ผ๋ฐ˜/๊ณต์šฉ API๊ฐ€ ์ข…์ข… ์˜๋„์ ์œผ๋กœ setter์— ํ—ˆ์šฉ๋˜๋Š” ์œ ํ˜•์„ ์™„ํ™”ํ•œ๋‹ค๋Š” ์‚ฌ์‹ค์ž…๋‹ˆ๋‹ค. ๊ทธ๋“ค์€ ๊ทธ๊ฒƒ์„ ๋ชจ๋‘ ์ˆ˜์šฉํ•˜๋Š” ์‚ถ์˜ ์งˆ ํ–ฅ์ƒ์œผ๋กœ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

API์˜ ์ƒ์‚ฐ์ž์ด์ž ์†Œ๋น„์ž์ธ ๊ฒฝ์šฐ ์ด๋Ÿฌํ•œ ์ข…๋ฅ˜์˜ ์ž‘์—…์ด ๋” ๋งŽ์€ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋ฌด์˜๋ฏธํ•ด ๋ณด์ผ ์ˆ˜ ์žˆ์ง€๋งŒ ๋Œ€๋Ÿ‰ ์†Œ๋น„๋ฅผ ์œ„ํ•œ API๋ฅผ ์„ค๊ณ„ํ•˜๋Š” ๊ฒฝ์šฐ์—๋Š” ๋งŽ์€ ์˜๋ฏธ๋ฅผ ๊ฐ€์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ๋‚˜๋Š” ์•„๋ฌด๋„ setter/getter๊ฐ€ _disjoint_ ์œ ํ˜•์„ ๊ฐ–๊ธฐ๋ฅผ ์›ํ•˜์ง€ ์•Š์„ ๊ฒƒ์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ ๋…ผ์˜๋˜๋Š” ๊ฒƒ์€ API ์ƒ์‚ฐ์ž๊ฐ€ API ์†Œ๋น„์ž์—๊ฒŒ getter๊ฐ€ setter์˜ ํ†ตํ•ฉ ์œ ํ˜•์˜ ์—„๊ฒฉํ•œ ํ•˜์œ„ ์ง‘ํ•ฉ์ธ ์œ ํ˜•์„ ๊ฐ€์ง„ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•  ๊ฒƒ์ด๋ผ๊ณ  ์ฃผ์žฅํ•œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ๋‚˜๋Š” ๋ˆ„๊ตฌ๋„ setter/getter๊ฐ€ ๋ถ„๋ฆฌ๋œ ์œ ํ˜•์„ ๊ฐ–๊ธฐ๋ฅผ ์›ํ•˜์ง€ ์•Š์„ ๊ฒƒ์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๊ฒƒ์— ๋Œ€ํ•œ ๋ฐ˜๋Œ€ ๊ด€์ ์„ ์ œ๊ณตํ•˜๊ธฐ ์œ„ํ•ด์„œ์ž…๋‹ˆ๋‹ค. setter/getter์— ๋Œ€ํ•ด ๋ถ„๋ฆฌ๋œ ์œ ํ˜•์„ ๊ฐ–๋Š” ๊ฒƒ์ด ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์—์„œ ์™„์ „ํžˆ ํ•ฉ๋ฒ•์ ์ด๊ธฐ ๋•Œ๋ฌธ์— ํ™•์‹คํžˆ ์›ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ œ ์ƒ๊ฐ์— ์ฃผ์š” ๋ชฉํ‘œ๋Š” (์ ์–ด๋„ .d.ts ์ˆ˜์ค€์—์„œ) ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์—์„œ ํ•ฉ๋ฒ•์ ์ธ ๋ชจ๋“  ๊ฒƒ์„ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์ž…๋ ฅํ•  ์ˆ˜ ์žˆ์„ ์ •๋„๋กœ ์œ ํ˜• ์‹œ์Šคํ…œ์„ ํ‘œํ˜„๋ ฅ ์žˆ๊ฒŒ ๋งŒ๋“œ๋Š” ๊ฒƒ์ด์–ด์•ผ ํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ์ „์—ญ ๊ฐ์ฒด๋‚˜ ํ•จ์ˆ˜ ๋“ฑ๊ณผ ๊ฐ™์€ ๋‚ด์žฅ์˜ ํ”„๋กœํ† ํƒ€์ž…์„ ๋ณ€๊ฒฝํ•˜๋Š” ๊ฒƒ์€ ์ข‹์€ ์Šต๊ด€์ด ์•„๋‹ˆ๋ผ๋Š” ๊ฒƒ์„ ์ดํ•ดํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์šฐ๋ฆฌ๋Š” ์—ฌ์ „ํžˆ .d.ts ํŒŒ์ผ์— ๊ทธ๋Ÿฐ ๊ฒƒ๋“ค์„ ์ž˜ ์ž…๋ ฅํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ ์•„๋ฌด๋„ ๊ทธ๊ฒƒ์„ ํ›„ํšŒํ•˜๋Š” ๊ฒƒ์„ ๋“ฃ์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋Š” ๊ทธ๋ ‡๊ฒŒ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(๋น„๋ก ์ž˜๋ชป ์„ค๊ณ„๋œ ์ผ๋ถ€ ์œ ํ˜• ์ •์˜ ํŒŒ์ผ์ด ํ™•์‹คํžˆ ์œ ํ˜•์ด ์ง€์ •๋œ ํŒŒ์ผ์— ํ‘œ์‹œ๋˜๊ธฐ๋Š” ํ•˜์ง€๋งŒ).

๋‚ด๊ฐ€ ์ œ์–ดํ•  ์ˆ˜ ์—†๋Š” ์˜ฌ๋ฐ”๋ฅธ ์œ ํ˜•์„ ๊ฐ–๊ธฐ ์œ„ํ•ด ์ด๊ฒƒ์ด ๊ธฐ๋Šฅ์ด ํ•„์š”ํ•œ ์ƒํ™ฉ์— ๋ด‰์ฐฉํ–ˆ์Šต๋‹ˆ๋‹ค. setter๋Š” getter์—์„œ ์ผ๊ด€๋˜๊ฒŒ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ๋Š” ๋ณด๋‹ค ์ž์œ ์ฃผ์˜์ ์ด๊ณ  ๋ณด๋‹ค ๋ณด์ˆ˜์ ์ธ ์œ ํ˜•์œผ๋กœ ๊ฐ•์ œํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์ด๋Ÿฐ ๊ธฐ๋Šฅ์ด ์žˆ์—ˆ์œผ๋ฉด ์ •๋ง ์ข‹๊ฒ ์Šต๋‹ˆ๋‹ค. JavaScript ์ฝ”๋“œ๋ฅผ TypeScript๋กœ ์ด์‹ํ•˜๊ณ  ์žˆ๋Š”๋ฐ, ์œ ํ˜• ์•ˆ์ „์„ฑ์„ ์›ํ•  ๊ฒฝ์šฐ setter๋ฅผ ๋ฆฌํŒฉํ† ๋งํ•ด์•ผ ํ•˜๋Š” ๊ฒƒ์€ ์ •๋ง ํฐ ๋ฌธ์ œ์ž…๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด, ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ฒƒ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

class Vector3 { /* ... */ }

type XYZ = Vector3 | [number, number, number] | {x: number, y: number, z: number}
type PropertyAnimator = (x: number, y: number, z: number, timestamp: number) => XYZ
type XYZSettables =  XYZ | PropertyAnimator

export class Transformable {
        // ...

        set position(newValue: XYZSettables) {
            this._setPropertyXYZ('position', newValue)
        }
        get position(): Vector3 {
            return this._props.position
        }

        // ...
}

์ƒ์ƒํ•  ์ˆ˜ ์žˆ๋“ฏ์ด ์‚ฌ์šฉ๋ฒ•์€ ๋งค์šฐ ์œ ์—ฐํ•ฉ๋‹ˆ๋‹ค.

const transform = new Transformable

// use an array
transform.position = [20, 30, 40]

// use an object
transform.position = {y: 30, z: 40} // skip `x` this time

// animate manually, a property directly
requestAnimationFrame((time) => {
  transform.position.x = 100 * Math.sin(time * 0.001)
})

// animate manually, with an array, which could be shared across instances
const pos = [10, 20, 30]
requestAnimationFrame((time) => {
  pos[2] = 100 * Math.sin(time * 0.001)
  transform.position = pos
})

// Animate with a property function
transform.position = (x, y, z, time) => [x, y, 100 * Math.sin(time * 0.001)]

// or a simple increment:
transform.position = (x, y, z) => [x, y, ++z]

// etc

// etc

// etc

4์‚ด์ž…๋‹ˆ๋‹ค. ์–ด๋–ป๊ฒŒ ์—ฌ์ „ํžˆ ํ•ด๊ฒฐ๋˜์ง€ ์•Š์Šต๋‹ˆ๊นŒ? ์ด ๊ธฐ๋Šฅ์€ ์œ„์˜ ์˜๊ฒฌ์—์„œ ์–ธ๊ธ‰ํ–ˆ๋“ฏ์ด ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค! ์ ์–ด๋„ ๋ฌธ์ œ๋ฅผ ๋‹ค์‹œ ์—ฌ๋Š” ๊ฒƒ์„ ๊ณ ๋ คํ•˜์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ?

๊ทธ๋ฆฌ๊ณ  ๋‚˜๋Š” @kitsonk ์— ์™„์ „ํžˆ ๋™์˜ํ•ฉ๋‹ˆ๋‹ค.

@kitsonk ์œ„์˜ ์˜๊ฒฌ์—์„œ ์„ค๋“๋ ฅ ์žˆ๋Š” ์‚ฌ์šฉ ์‚ฌ๋ก€๊ฐ€ ์ถฉ๋ถ„ํžˆ ์ œ๊ณต๋˜์—ˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ํ˜„์žฌ ๋””์ž์ธ์€ ์ด ์ œํ•œ์ด ์žˆ๋Š” ๋Œ€๋ถ€๋ถ„์˜ ๋‹ค๋ฅธ ์œ ํ˜• ์–ธ์–ด์˜ ๊ณตํ†ต ํŒจํ„ด์„ ๋”ฐ๋ฅด์ง€๋งŒ Javascript ์ปจํ…์ŠคํŠธ์—์„œ๋Š” ๋ถˆํ•„์š”ํ•˜๊ณ  ์ง€๋‚˜์น˜๊ฒŒ ์ œํ•œ์ ์ž…๋‹ˆ๋‹ค. ์„ค๊ณ„์— ์˜ํ•œ ๊ฒƒ์ด์ง€๋งŒ ์„ค๊ณ„๊ฐ€ ์ž˜๋ชป๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

TypeScript 3.6์€ ์„ ์–ธ ํŒŒ์ผ์— ์ ‘๊ทผ์ž๋ฅผ ์ž…๋ ฅํ•˜๊ธฐ ์œ„ํ•œ ๊ตฌ๋ฌธ์„ ๋„์ž… ํ•˜๋ฉด์„œ getter์™€ setter์˜ ์œ ํ˜•์ด ๋™์ผํ•ด์•ผ ํ•œ๋‹ค๋Š” ์ œํ•œ์„ ์œ ์ง€ํ–ˆ์Šต๋‹ˆ๋‹ค.

์šฐ๋ฆฌ์˜ UI ํˆดํ‚ท์€ ์ž๋™ ์บ์ŠคํŒ… setter์— ํฌ๊ฒŒ ์˜์กดํ•˜๋Š”๋ฐ, ์—ฌ๊ธฐ์„œ setter๋Š” getter์—์„œ ๋ฐ˜ํ™˜๋œ ๋‹จ์ผ ์œ ํ˜•๋ณด๋‹ค ๋” ๋งŽ์€ ์œ ํ˜•์„ ํ—ˆ์šฉํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ TS๊ฐ€ ์ด ํŒจํ„ด์„ ์œ ํ˜• ์•ˆ์ „ํ•˜๊ฒŒ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•์„ ์ œ๊ณตํ•˜๋ฉด ์ข‹์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

@RyanCavanaugh ๊ฐ€ 3๋…„ ์ „์— ์ด ๊ธฐ๋Šฅ์— ๋Œ€ํ•ด ๊ฐ€์žฅ ๊ตฌ์ฒด์ ์ธ ๋ฐ˜๋ฐ•์„ ํ•œ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ์ตœ๊ทผ์— ๋ณด๊ณ ๋œ DOM ์‚ฌ์šฉ ์‚ฌ๋ก€์™€ ์ƒˆ๋กœ์šด ์„ ์–ธ ๊ตฌ๋ฌธ์˜ ๊ฐ€์šฉ์„ฑ์ด ์ƒˆ๋กœ์šด ๊ฒฐ์ •์„ ํ—ˆ์šฉํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ๊ถ๊ธˆํ•ฉ๋‹ˆ๋‹ค.

๋„ค, ๊ทธ ์ƒˆ๋กœ์šด ๊ธฐ๋Šฅ์„ ๋ณด์ž๋งˆ์ž ๋ฐ”๋กœ ์ด ๊ธฐ๋Šฅ ์š”์ฒญ์ด ์ƒ๊ฐ๋‚ฌ์Šต๋‹ˆ๋‹ค. ๋‚˜๋Š” ๋˜ํ•œ ์šฐ๋ฆฌ์˜ UI ํ”„๋ ˆ์ž„์›Œํฌ์˜ ๋ชฉ์ ์„ ์œ„ํ•ด ๊ทธ๊ฒƒ์„ ์›ํ•ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ์‹ค์ œ ์‚ฌ์šฉ ์‚ฌ๋ก€์ž…๋‹ˆ๋‹ค.

TSConf 2019 ๊ฐ€ 10์›” 11์ผ ์— ๊ฐœ์ตœ๋ฉ๋‹ˆ๋‹ค. ๊ธฐํšŒ๊ฐ€ ๋œ๋‹ค๋ฉด Q&A ์„ธ์…˜์—์„œ ์ข‹์€ ํšŒ์ƒ์ด ๋  ๊ฒƒ ๊ฐ™์•„์š” ๐Ÿค”

์ด ๊ธด ์Šค๋ ˆ๋“œ์—์„œ ์ด์ „์— ๋งํ–ˆ์„์ง€ ๋ชจ๋ฅด์ง€๋งŒ ๋ฐ˜๋ณตํ•ด์•ผ ํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

TypeScript์˜ IMO ํ‘œํ˜„ํ˜• ์‹œ์Šคํ…œ์€ ๋‘ ๊ฐ€์ง€ ๋ณ„๊ฐœ์˜ ๋ชฉ์ ์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค. ์ฒซ ๋ฒˆ์งธ๋Š” ๋” ์•ˆ์ „ํ•œ ์ƒˆ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๊ทธ๊ฒƒ์ด ์œ ์ผํ•œ ๋ชฉ์ ์ด๋ผ๋ฉด ์•„๋งˆ๋„ ์ด ์‹œ๋‚˜๋ฆฌ์˜ค๋ฅผ ํ—ˆ์šฉํ•˜์ง€ ์•Š์œผ๋ฉด ์ฝ”๋“œ๊ฐ€ ๋” ์•ˆ์ „ํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ์ด ์‚ฌ์šฉ ์‚ฌ๋ก€๋ฅผ ํ”ผํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์ฃผ์žฅ์„ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ ๋‘ ๋ฒˆ์งธ ๋ชฉ์ ์€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ๋™์ž‘ ์„ ์žˆ๋Š” ๊ทธ๋Œ€๋กœ ์บก์ฒ˜ํ•˜๋Š” ๊ฒƒ์ด๋ฉฐ DOM ๋ฐ JS ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์—์„œ setter์—์„œ ์ž๋™ ๊ฐ•์ œ ๋ณ€ํ™˜๋˜์ง€๋งŒ getter์—์„œ ํ•˜๋‚˜์˜ ์˜ˆ์ƒ ์œ ํ˜•์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฒƒ์ด ํ•ฉ๋ฆฌ์ ์œผ๋กœ ์ผ๋ฐ˜์ ์ธ ๊ด€ํ–‰์ž…๋‹ˆ๋‹ค. ์œ ํ˜• ์‹œ์Šคํ…œ์—์„œ ์ด๋ฅผ ์บก์ฒ˜ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๋ฉด ๊ธฐ์กด ํ”„๋ ˆ์ž„์›Œํฌ ๋ฅผ ์žˆ๋Š” ๊ทธ๋Œ€๋กœ ๋” ์ •ํ™•ํ•˜๊ฒŒ ์„ค๋ช…ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค .

์ ์–ด๋„ Design Limitation ๋Š” ์—ฌ๊ธฐ์—์„œ ์ œ๊ฑฐํ•  ์ˆ˜ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ๋” ์ด์ƒ ๊ด€๋ จ์ด ์—†๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

์ด๊ฒƒ์€ ์‹ค์ œ๋กœ ํ”„๋ก์‹œ๋„ ์ˆ˜ํ–‰ํ•˜๊ธฐ ์–ด๋ ต๊ฒŒ ๋งŒ๋“ญ๋‹ˆ๋‹ค.
https://stackoverflow.com/questions/57948140/typescript-proxy-which-returns-a-different-type-from-get-than-it-takes-for-set

์ด๊ฒƒ์€ ๋ถ„๋ช…ํžˆ #33749 .style.display = ...something nullable... ๋” ์ด์ƒ ์œ ํ˜• ๊ฒ€์‚ฌ๋ฅผ ํ•˜์ง€ ์•Š๋Š”๋‹ค๋Š” ์‚ฌ์‹ค์— ๋Œ€ํ•œ ์ด์œ ์ž…๋‹ˆ๋‹ค. ์ด๋Š” ๋ฌดํšจ์„ฑ ์ •ํ™•์„ฑ ๋ฌธ์ œ๋กœ ์ œ์‹œ๋ฉ๋‹ˆ๋‹ค. ๊ทธ๊ฑด ์ข€ ๋ป”๋ป”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๊นŒ? ๋ฒ„๊ทธ ์ˆ˜์ •์œผ๋กœ ์ž˜๋ชป๋œ ๋ ˆ์ด๋ธ”์ด ์ง€์ •๋˜์—ˆ์„ ๋•Œ ์ƒˆ๋กœ์šด ์ฃผ์š” ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ํŒŒ์•…ํ•ด์•ผ ํ•˜๋Š” ๊ฒƒ์€ ์„ฑ๊ฐ€์‹  ์ผ์ž…๋‹ˆ๋‹ค. ๊ฐœ์ธ์ ์œผ๋กœ, ๋‚˜๋Š” null ์— ๋นˆ ๋ฌธ์ž์—ด์ด ํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค "๊ธฐ๋ณธ๊ฐ’ ์‚ฌ์šฉ"์ด๋ผ๋Š” ํŠน๋ณ„ํ•œ ๋™์ž‘์ด ์žˆ๋‹ค๋Š” ๊ฒƒ์ด ํ›จ์”ฌ ๋œ ๋†€๋ž๋‹ค๋Š” ๊ฒƒ์„ ์•Œ์•˜์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  typescipt 3.7๊นŒ์ง€๋Š” null์„ ์‚ฌ์šฉํ•˜์—ฌ ์บก์ฒ˜ํ•˜๋Š” ๊ฒƒ์„ ์„ ํ˜ธํ–ˆ์Šต๋‹ˆ๋‹ค. ์–ด๋–ค ๊ฒฝ์šฐ๋“  ์ด ์ œํ•œ์„ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ์˜๋„์ ์œผ๋กœ ์ž˜๋ชป๋œ ์œ ํ˜• ์ฃผ์„์— ๋ ˆ์ด๋ธ”์„ ์ง€์ •ํ•˜๋ฉด ์—…๊ทธ๋ ˆ์ด๋“œ ๋ฌธ์ œ๋ฅผ ๋ถ„๋ฅ˜ํ•˜๋Š” ์‹œ๊ฐ„์„ ์ ˆ์•ฝํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋˜ํ•œ ์ด๋ฅผ ์œ„ํ•œ ๊ฒฝ๋กœ๋ฅผ ์ฐพ๋Š” ๋ฐ ๊ด€์‹ฌ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์•ฐ๋น„์–ธํŠธ ์ปจํ…์ŠคํŠธ์—์„œ๋งŒ ํ—ˆ์šฉ๋œ๋‹ค๋ฉด ์–ด๋–ป๊ฒŒ ๋ ๊นŒ์š”? @RyanCavanaugh ๊ฐ€ ๋ณต์žก์„ฑ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋ ๊นŒ์š”?

์ด์— ๋Œ€ํ•œ ๋‚˜์˜ ์‚ฌ์šฉ ์‚ฌ๋ก€๋Š” ํ”„๋ก์‹œ๊ฐ€ ์•ฝ์†์„ ๋ฐ˜ํ™˜ํ•˜์ง€๋งŒ ์„ค์ • ์ž‘์—…์ด ์•ฝ์†์„ ์„ค์ •ํ•˜์ง€ ์•Š๋Š” API๊ฐ€ ์žˆ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ง€๊ธˆ์€ TypeScript์—์„œ ์ด๊ฒƒ์„ ์„ค๋ช…ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

let post = await loadPost()
let user = await loadUser()
post.author = user // Proxy handles links these two objects via remote IDs
await save(post)

// Somewhere else in code
let post = await loadPost()
let author = await post.author

ํ˜•์‹ ์ˆ˜์ • ๋„ค์ดํ‹ฐ๋ธŒ ๊ธฐ๋Šฅ์ด๋“ , ์ผ๋ฐ˜์ ์ธ ํ”„๋ก์‹œ์ด๋“ , TypeScript๋Š” ์ด๋Ÿฌํ•œ ์œ ํ˜•์˜ ๊ธฐ๋Šฅ์ด ์‹ค์ˆ˜์˜€๋‹ค๋Š” ์ž…์žฅ์ธ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

๊ทธ๋“ค์€ ์ด ๋ชฉ๋ก์—์„œ 6๋ฒˆ๊ณผ 7๋ฒˆ์„ ์ œ๊ฑฐํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค(https://github.com/Microsoft/TypeScript/wiki/TypeScript-Design-Goals#goals).

๋‚ด ๋ฌธ์ œ

set ๋ฉ”์„œ๋“œ์—์„œ ํ•ญ๋ชฉ์„ ๋ฐฐ์—ด๋กœ ํ‘ธ์‹œํ•˜๊ณ  get ๋ฉ”์„œ๋“œ์—์„œ ์ „์ฒด ๋ฐฐ์—ด์„ ๊ฐ€์ ธ์˜ค๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค. ์ง€๊ธˆ์€ ์ž˜ ์ž‘๋™ํ•˜๋Š” set myArray(...value: string[]) ๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด ๋ฌธ์ œ์— ๋งŽ์ด ๋ถ€๋”ช์ณค์Šต๋‹ˆ๋‹ค... ์ด ๋ฌธ์ œ๋ฅผ ์ œ๊ฑฐํ•˜๋Š” ๊ฒƒ์„ ๊ณ ๋ คํ•˜์‹ญ์‹œ์˜ค. ์ •๋ณด ๋˜๋Š” ๊ฒฝ๊ณ ๋Š” ์ด์— ๋Œ€ํ•ด ์ž˜ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค.

์˜ˆ(ํ•˜๊ณ  ์‹ถ์€ ๊ฒƒ)

class MyClass {
   _myArray: string[] = [];

   set myArray(value: string) {
      this._myArray.push(value);
   }

   get myArray(): string[] {
      return this._myArray;
   }
}

์˜ˆ (๋‚ด๊ฐ€ํ•ด์•ผ ํ•  ์ผ)

class MyClass {
   _myArray: string[] = [];

   set myArray(...value: string[]) {
      this._myArray.push(value[0]);
   }

   get myArray(): string[] {
      return this._myArray;
   }
}

๋‚ด๊ฐ€ ํ•„์š”ํ•  ๋•Œ ์ƒ๊ฐํ•ด๋‚ธ ํ•œ ๊ฐ€์ง€ ํ•ด๊ฒฐ์ฑ…์€ ์†์„ฑ์„ union type ๋กœ ์„ค์ •ํ•˜๋Š” ๊ฒƒ์ด์—ˆ์Šต๋‹ˆ๋‹ค. ๋‚ด ์‹œ๊ฐ„์€ API์—์„œ ๋ฌธ์ž์—ด๋กœ ์ž…๋ ฅ๋˜์ง€๋งŒ ๋‚ด UI์— ๋Œ€ํ•œ Moment ๊ฐœ์ฒด๋กœ ์„ค์ •ํ•ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

๋‚˜์˜ ์˜ˆ

class TimeStorage {
    _startDate: string | Moment = ""
    _endDate: string | Moment = ""

    set startDate(date: Moment | string) {
        this._startDate = moment(date).utc()
    }
    get startDate(): Moment | string {
        return moment.utc(this._startDate)
    }

    set endDate(date: Moment) { 
        this._endDate = moment.utc(date)
    }
    get endDate() { 
        return moment.utc(this._endDate)
    }
}

๋‚˜๋Š” ํŒŒํ‹ฐ์— ์กฐ๊ธˆ ๋Šฆ์—ˆ์ง€๋งŒ ์ตœ๊ทผ์—์ด ๋ฌธ์ œ์— ์ง๋ฉดํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๊ฒƒ์€ ํฅ๋ฏธ๋กœ์šด ๋”œ๋ ˆ๋งˆ์ด๋ฏ€๋กœ ์กฐ๊ธˆ ๋งŒ์ง€์ž‘๊ฑฐ๋ฆฌ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๊ฒƒ์ด ์šฐ๋ฆฌ๊ฐ€ ๋งŒ๋“ค๊ณ ์ž ํ•˜๋Š” ๊ฒƒ์ด๋ผ๊ณ  ๊ฐ€์ •ํ•ด ๋ด…์‹œ๋‹ค. ๋ฌธ์ž์—ด๊ณผ ์ˆซ์ž(์–ด๋–ค ์šฉ๋„๋กœ๋“ )๋ฅผ ํ—ˆ์šฉํ•˜๋Š” ์†์„ฑ์„ ๊ฐ€์ง€๊ณ  ์žˆ์ง€๋งŒ ์†์„ฑ์€ ์‹ค์ œ๋กœ ๋ฌธ์ž์—ด๋กœ ์ €์žฅ๋˜์–ด ์žˆ๋Š” ๊ฐ„๋‹จํ•œ ํด๋ž˜์Šค์ž…๋‹ˆ๋‹ค.

class Foo {
    constructor() {
        this._bar = '';
        this.baz = '';
    }

    // error: 'get' and 'set' accessor must have the same type.(2380)
    get bar(): string {
        return this._bar;
    }

    // error: 'get' and 'set' accessor must have the same type.(2380)
    set bar(value: string | number) {
        this._bar = value.toString();
    }

    public baz: string;
    private _bar: string;
}

์ด๊ฒƒ์€ ๋ถˆ๊ฐ€๋Šฅํ•˜๊ณ  ์—ฌ์ „ํžˆ ๊ฐ•๋ ฅํ•œ ํƒ€์ดํ•‘์„ ์›ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ถ”๊ฐ€ ์ฝ”๋“œ๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ์ด์ œ ๋ˆ„๊ตฐ๊ฐ€๊ฐ€ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์†์„ฑ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ๋งŒ๋“ค์—ˆ๋‹ค๊ณ  ์˜ˆ๋ฅผ ๋“ค์–ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

/**
 * Abstract base class for properties.
 */
abstract class Property<GetType, SetType> {
    abstract get(): GetType;
    abstract set(value: SetType): void;
}

/**
 * Proxify an object so that it's get and set accessors are proxied to
 * the corresponding Property `get` and `set` calls.
 */
function proxify<T extends object>(obj: T) {
    return new Proxy<any>(obj, {
        get(target, key) {
            const prop = target[key];
            return (prop instanceof Property) ? prop.get() : prop;
        },
        set(target, key, value) {
            const prop = target[key];
            if (prop instanceof Property) {
                prop.set(value);
            } else {
                target[key] = value;
            }
            return true;
        }
    });
}

์ด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ํด๋ž˜์Šค์— ๋Œ€ํ•œ typed ์†์„ฑ์„ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

class Bar extends Property<string, string | number> {
    constructor(bar: string | number) {
        super();
        this.set(bar);
    }

    get(): string {
        return this._bar;
    }

    set(value: string | number) {
        this._bar = value.toString();
    }

    private _bar: string;
}

class Foo {
    constructor() {
        this.bar = new Bar('');
        this.baz = '';
    }

    public bar: Bar;
    public baz: string;
}

๊ทธ๋Ÿฐ ๋‹ค์Œ ์ด ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด bar ์— ๋Œ€ํ•œ ์•ˆ์ „ํ•œ getter ๋ฐ setter ์œ ํ˜•์„ ๊ฐ–๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

const foo = new Foo();

// use property's typed setter
foo.bar.set(42);
foo.baz = 'foobar';

// use property's typed getter
// output: 42 foobar
console.log(foo.bar.get(), foo.baz);

๊ทธ๋ฆฌ๊ณ  ์†์„ฑ setter ๋˜๋Š” getter๋ฅผ ๋” ๋™์ ์œผ๋กœ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ proxify ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ž˜ํ•‘ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

const foo = new Foo();

// use proxified property setters
Object.assign(proxify(foo), { bar: 100, baz: 'hello world' });

// use property's typed getter
// output: 100 hello world
console.log(foo.bar.get(), foo.baz);

// use proxified property getters
// output: {"bar":"100","baz":"hello world"}
console.log(JSON.stringify(proxify(foo)));

๋ฉด์ฑ… ์กฐํ•ญ: ๋ˆ„๊ตฐ๊ฐ€ ์ด ์ฝ”๋“œ๋ฅผ ๊ฐ€์ ธ์™€์„œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์— ๋„ฃ๊ฑฐ๋‚˜ ์›ํ•˜๋Š” ๋Œ€๋กœ ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด ์ž์œ ๋กญ๊ฒŒ ํ•˜์‹ญ์‹œ์˜ค. ๋„ˆ๋ฌด ๊ฒŒ์œผ๋ฅด๋‹ค.

๋ช‡ ๊ฐ€์ง€ ์ถ”๊ฐ€ ๋ฉ”๋ชจ๋งŒ ํ•˜๋ฉด ์ด ๊ธด ๋ชฉ๋ก์— ์ŠคํŒธ ๋ฉ”์ผ์„ ๋ณด๋‚ด์ง€ ์•Š๊ฒ ๋‹ค๊ณ  ์•ฝ์†ํ•ฉ๋‹ˆ๋‹ค!

์ด๊ฒƒ์„ ์ƒ์ƒ์˜ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์— ์ถ”๊ฐ€ํ•˜๋ฉด:

/**
 * Create a property with custom `get` and `set` accessors.
 */
function property<GetType, SetType>(property: {
    get: () => GetType,
    set: (value: SetType) => void
}) {
    const obj = { ...property };
    Object.setPrototypeOf(obj, Property.prototype);
    return obj;
}

์šฐ๋ฆฌ๋Š” ์›๋ž˜ ํด๋ž˜์Šค์— ์กฐ๊ธˆ ๋” ๊ฐ€๊นŒ์šด ๊ตฌํ˜„์„ ์–ป์—ˆ๊ณ  ๊ฐ€์žฅ ์ค‘์š”ํ•œ ๊ฒƒ์€ this ์— ์•ก์„ธ์Šคํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

class Foo {
    constructor() {
        this._bar = '';
        this.baz = '';
    }

    public bar = property({
        get: (): string => {
            return this._bar;
        },
        set: (value: string | number) => {
            this._bar = value.toString();
        }
    });

    public baz: string;
    private _bar: string;
}

์„ธ์ƒ์—์„œ ๊ฐ€์žฅ ์˜ˆ์œ ๊ฒƒ์€ ์•„๋‹ˆ์ง€๋งŒ ํšจ๊ณผ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ˆ„๊ตฐ๊ฐ€๊ฐ€ ์ด๊ฒƒ์„ ๊ฐœ์„ ํ•˜๊ณ  ์‹ค์ œ๋กœ ๋ฉ‹์ง„ ๊ฒƒ์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด ์Šค๋ ˆ๋“œ๋ฅผ ์ฝ๋Š” ๊ฐœ์ธ์ด ์ด ๊ธฐ๋Šฅ์ด ์ค‘์š”ํ•˜๋‹ค๊ณ  ํ™•์‹ ํ•˜์ง€ ๋ชปํ•˜๋Š” ๊ฒฝ์šฐ ๋ฅผ ๋Œ€๋น„ํ•˜์—ฌ Angular๊ฐ€ ๋ฐฉ๊ธˆ ์†Œ๊ฐœํ•œ ์ด ์—„์ฒญ๋‚˜๊ฒŒ ์ถ”ํ•œ ํ•ดํ‚น์„ ์•Œ๋ ค๋“œ๋ฆฝ๋‹ˆ๋‹ค.

์—ฌ๊ธฐ์—์„œ ๊ฐ’ ์œ ํ˜•์„ ๋ถ€์šธ์—์„œ ๋ถ€์šธ|''๋กœ ๋ณ€๊ฒฝํ•˜์—ฌ setter๊ฐ€ ์‹ค์ œ๋กœ ํ—ˆ์šฉํ•˜๋Š” ๊ฐ’ โ€‹โ€‹์„ธํŠธ์™€ ์ผ์น˜์‹œํ‚ค๋Š” ๊ฒƒ์ด ์ด์ƒ์ ์ž…๋‹ˆ๋‹ค. TypeScript๋Š” getter์™€ setter๊ฐ€ ๋ชจ๋‘ ๋™์ผํ•œ ์œ ํ˜•์„ ๊ฐ€์ ธ์•ผ ํ•˜๋ฏ€๋กœ getter๊ฐ€ ๋ถ€์šธ์„ ๋ฐ˜ํ™˜ํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ setter๋Š” ๋” ์ข์€ ์œ ํ˜•์œผ๋กœ ๊ณ ์ •๋ฉ๋‹ˆ๋‹ค.... Angular๋Š” @Input()์— ๋Œ€ํ•ด ๋” ๋„“๊ณ  ํ—ˆ์šฉ์ ์ธ ์œ ํ˜• ๊ฒ€์‚ฌ๋ฅผ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค. ์ž…๋ ฅ ํ•„๋“œ ์ž์ฒด์— ๋Œ€ํ•ด ์„ ์–ธ๋ฉ๋‹ˆ๋‹ค. ๊ตฌ์„ฑ ์š”์†Œ ํด๋ž˜์Šค์— ngAcceptInputType_ ์ ‘๋‘์‚ฌ๊ฐ€ ์žˆ๋Š” ์ •์  ์†์„ฑ์„ ์ถ”๊ฐ€ํ•˜์—ฌ ์ด๋ฅผ ํ™œ์„ฑํ™”ํ•ฉ๋‹ˆ๋‹ค.

````
ํด๋ž˜์Šค ์ œ์ถœ ๋ฒ„ํŠผ {
private _disabled: ๋ถ€์šธ;

๋น„ํ™œ์„ฑํ™”(): ๋ถ€์šธ {
์ด๊ฒƒ์„ ๋ฐ˜ํ™˜ํ•˜์‹ญ์‹œ์˜ค._disabled;
}

๋น„ํ™œ์„ฑํ™” ์„ค์ •(๊ฐ’: ๋ถ€์šธ) {
this._disabled = (๊ฐ’ === '') || ๊ฐ’;
}

์ •์  ngAcceptInputType_disabled: ๋ถ€์šธ|'';
}
````

์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•ด ์ฃผ์„ธ์š” .

๋„ค, ๋ฌธ์ž ๊ทธ๋Œ€๋กœ Angular๊ฐ€ ์‚ฌ์šฉํ•˜๋ ค๋Š” ํŒจํ„ด์„ ์ง€์›ํ•˜๊ธฐ ์œ„ํ•ด ์ด ์ถ”์•…ํ•จ์ด ๊ณณ๊ณณ์— ์žˆ์Šต๋‹ˆ๋‹ค. ํ˜„์žฌ์˜ ์ œํ•œ์€ ๋„ˆ๋ฌด ๋…๋‹จ์ ์ž…๋‹ˆ๋‹ค.

TS๊ฐ€ ์›น ๋žœ๋“œ์—์„œ ์ „์ฒด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ๋ชจ๋ธ๋งํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋˜๊ธฐ๋ฅผ ์›ํ•œ๋‹ค๋ฉด ๋œ ๋…๋‹จ์ ์ธ ๋…ธ๋ ฅ์„ ๊ธฐ์šธ์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ๋ชจ๋“  ๋””์ž์ธ์„ ๋ชจ๋ธ๋งํ•˜์ง€ ๋ชปํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ด ์‹œ์ ์—์„œ ์ด ๋ฌธ์ œ๊ฐ€ ๋‹ค์‹œ ์—ด๋ฆฌ์ง€ ์•Š๋Š” ์ด์œ ๋ฅผ ์ „๋‹ฌํ•˜๋Š” ์ฑ…์ž„์€ ๊ธฐ์—ฌ์ž์—๊ฒŒ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ํ˜„์‹œ์ ์—์„œ๋„ ์ด์— ๋Œ€ํ•ด ๊ฐ•๋ ฅํ•˜๊ฒŒ ๋ฐ˜๋Œ€ํ•˜๋Š” ๊ธฐ๊ณ ์œ„์›์ด ์žˆ์Šต๋‹ˆ๊นŒ?

W3C ์‚ฌ์–‘๊ณผ ์ผ์น˜ํ•˜๋Š” NodeJ์šฉ DOM ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ๊ตฌ์ถ•ํ•˜๊ณ  ์žˆ์ง€๋งŒ ์ด Typescript ๋ฌธ์ œ๋กœ ์ธํ•ด ๋ถˆ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. ๋ชจ๋“  ์—…๋ฐ์ดํŠธ?

TypeScript์˜ ํ•ต์‹ฌ ํŒ€ ๋‚ด ์ผ๋ถ€๊ฐ€ ์ง€๊ตฌ์ƒ์—์„œ ๊ฐ€์žฅ ๋งŽ์ด ์‚ฌ์šฉ๋˜๋Š” JavaScript ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ค‘ ํ•˜๋‚˜์ธ DOM์„ ์žฌ์ƒ์„ฑํ•˜๊ธฐ ์œ„ํ•ด ํ•„์š”ํ•œ ๊ธฐ๋Šฅ์— ๋ฐ˜๋Œ€ํ•œ๋‹ค๋Š” ์‚ฌ์‹ค์ด ์ €์—๊ฒŒ๋Š” ์ถฉ๊ฒฉ์ ์ž…๋‹ˆ๋‹ค.

a) W3C DOM ์‚ฌ์–‘์˜ ๋งŽ์€ ๋ถ€๋ถ„์„ ๊ตฌํ˜„ํ•˜๋Š” ๋™์•ˆ b) TypeScript์˜ ์œ ํ˜• ์‹œ์Šคํ…œ์„ ์‚ฌ์šฉํ•˜๋Š” ๋‹ค๋ฅธ ๋ฐฉ๋ฒ•์€ ์—†์Šต๋‹ˆ๋‹ค any

typescriptlang.org์˜ ํ™ˆํŽ˜์ด์ง€๋Š” ํ˜„์žฌ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ •ํ™•ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

TypeScript๋Š” ์ผ๋ฐ˜ JavaScript๋กœ ์ปดํŒŒ์ผ๋˜๋Š” JavaScript์˜ ์œ ํ˜•์ด ์ง€์ •๋œ ์ƒ์œ„ ์ง‘ํ•ฉ ์ž…๋‹ˆ๋‹ค.

JavaScript์˜ DOM ์‚ฌ์–‘์„ ๋‹ค์‹œ ๋งŒ๋“ค ์ˆ˜ ์—†๋‹ค๋Š” ๊ฒƒ์€ TypeScript๊ฐ€ ์—ฌ์ „ํžˆ ์ƒ์œ„ ์ง‘ํ•ฉ ์ด ์•„๋‹ˆ๋ผ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์˜ ํ•˜์œ„ ์ง‘ํ•ฉ์ž„์„ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค.

์ด ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•˜๋Š” ๊ฒƒ๊ณผ ๊ด€๋ จํ•˜์—ฌ ์ €๋Š” @gmurray81 ๋ฐ getter์˜ ์œ ํ˜•์ด setter์˜ ๊ณต์šฉ์ฒด ์œ ํ˜•์˜ ํ•˜์œ„ ์ง‘ํ•ฉ์ด์–ด์•ผ ํ•œ๋‹ค๊ณ  ์ฃผ์žฅํ•œ ๋งŽ์€ ๋‹ค๋ฅธ ์‚ฌ๋žŒ๋“ค์˜ ์˜๊ฒฌ์— ๋™์˜ํ•ฉ๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์—ฐ๊ฒฐ๋˜์ง€ ์•Š์€ ์ž…๋ ฅ์ด ๋ฐœ์ƒํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ด ์ ‘๊ทผ ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•˜๋ฉด setter์˜ ํ•จ์ˆ˜๊ฐ€ getter์˜ ์œ ํ˜•์„ ์†์ƒ์‹œํ‚ค์ง€ ์•Š๊ณ  ์ž…๋ ฅ์„ ์ •๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(์˜ˆ: any ์‚ฌ์šฉ์— ์˜์กดํ•ด์•ผ ํ•จ).

์—ฌ๊ธฐ ๋‚ด๊ฐ€ ํ•  ์ˆ˜์—†๋Š” ์ผ์ด ์žˆ์Šต๋‹ˆ๋‹ค. JS์—์„œ๋Š” ๋น„์Šทํ•œ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ–ˆ์ง€๋งŒ TS์—์„œ๋Š” ํ•  ์ˆ˜ ์—†๋Š” ๊ฐ„๋‹จํ•œ ์ž‘์—…์ž…๋‹ˆ๋‹ค.

์‹ค์ œ๋กœ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋Š” 4๋…„ ๋ฌธ์ œ.

export const enum Conns {
  none = 0, d = 1, u = 2, ud = 3,
  r = 4, rd = 5, ru = 6, rud = 7,
  l = 8, ld = 9, lu = 10, lud = 11,
  lr = 12, lrd = 13, lru = 14, lrud = 15,
  total = 16
}

class  Tile {
  public connections = Conns.none;

  get connLeft() { return this.connections & Conns.l; };

  set connLeft(val: boolean) { this.connections = val ? (this.connections | Conns.l) : (this.connections & ~Conns.l); }
}

์ง€๊ธˆ ์ด ๋ฌธ์ œ์— ์ง๋ฉดํ•ด ์žˆ์Šต๋‹ˆ๋‹ค. ์•„๋ž˜๋Š” @calebjclark ๋ฅผ ์ธ์šฉํ•˜๋Š” ํ•ฉ๋ฆฌ์ ์ธ ํ•ด๊ฒฐ์ฑ…์ฒ˜๋Ÿผ ๋ณด์ž…๋‹ˆ๋‹ค.

์ด ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•˜๋Š” ๊ฒƒ๊ณผ ๊ด€๋ จํ•˜์—ฌ ์ €๋Š” @gmurray81 ๋ฐ getter์˜ ์œ ํ˜•์ด setter์˜ ๊ณต์šฉ์ฒด ์œ ํ˜•์˜ ํ•˜์œ„ ์ง‘ํ•ฉ์ด์–ด์•ผ ํ•œ๋‹ค๊ณ  ์ฃผ์žฅํ•œ ๋งŽ์€ ๋‹ค๋ฅธ ์‚ฌ๋žŒ๋“ค์˜ ์˜๊ฒฌ์— ๋™์˜ํ•ฉ๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์—ฐ๊ฒฐ๋˜์ง€ ์•Š์€ ์ž…๋ ฅ์ด ๋ฐœ์ƒํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ด ์ ‘๊ทผ ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•˜๋ฉด setter์˜ ๊ธฐ๋Šฅ์ด getter์˜ ์œ ํ˜•์„ ํŒŒ๊ดดํ•˜์ง€ ์•Š๊ณ  ์ž…๋ ฅ์„ ์ •๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(์ฆ‰, any๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ).

getter๊ฐ€ setter ์œ ํ˜•์˜ ํ•˜์œ„ ์ง‘ํ•ฉ์ด๊ธฐ ๋•Œ๋ฌธ์— ๋ถˆํ•„์š”ํ•˜๊ฒŒ ์ œํ•œ์ ์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ์‹ค์ œ๋กœ ๊ตฌํ˜„์ด ํ•ญ์ƒ getter ์œ ํ˜•์˜ ํ•˜์œ„ ์œ ํ˜•์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ•œ setter ์œ ํ˜•์€ ์ด๋ก ์ ์œผ๋กœ ๋ง ๊ทธ๋Œ€๋กœ ๋ฌด์—‡์ด๋“  ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. setter๊ฐ€ getter ์œ ํ˜•์˜ ์ƒ์œ„ ์œ ํ˜•์ด ๋˜๋„๋ก ์š”๊ตฌํ•˜๋Š” ๊ฒƒ์€ ์ด ํ‹ฐ์ผ“์— ์ œ์‹œ๋œ ๋ช‡ ๊ฐ€์ง€ ์‚ฌ์šฉ ์‚ฌ๋ก€๋ฅผ ์ถฉ์กฑํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ๋‚˜์ค‘์— ๋ฐ˜๋“œ์‹œ ๋ถˆ๋งŒ์„ ์ œ๊ธฐํ•  ์ˆ˜ ์žˆ๋Š” ์ผ์ข…์˜ ์ด์ƒํ•œ ์ œํ•œ์ž…๋‹ˆ๋‹ค.

์ฆ‰, ํด๋ž˜์Šค๋Š” ์•”์‹œ์ ์œผ๋กœ ์ธํ„ฐํŽ˜์ด์Šค์ด๊ธฐ๋„ ํ•˜๋ฉฐ getter ๋ฐ setter๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ์ธํ„ฐํŽ˜์ด์Šค์— ํ‘œ์‹œ๋˜์ง€ ์•Š๋Š” ๊ตฌํ˜„ ์„ธ๋ถ€ ์ •๋ณด์ž…๋‹ˆ๋‹ค. OP์˜ ์˜ˆ์—์„œ๋Š” type MyClass = { myDate(): moment.Moment; } ๋กœ ๋๋‚ฉ๋‹ˆ๋‹ค. ์ด ์ƒˆ๋กœ์šด getter ๋ฐ setter ์œ ํ˜•์„ ์ธํ„ฐํŽ˜์ด์Šค์˜ ์ผ๋ถ€๋กœ ์–ด๋–ป๊ฒŒ๋“  ๋…ธ์ถœํ•ด์•ผ ํ•˜์ง€๋งŒ ๊ทธ๊ฒƒ์ด ๋ฐ”๋žŒ์งํ•œ ์ด์œ ๋ฅผ ๊ฐœ์ธ์ ์œผ๋กœ ์•Œ์ง€ ๋ชปํ•ฉ๋‹ˆ๋‹ค.

์ด ๋ฌธ์ œ๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ = ๋ฐ === ์—ฐ์‚ฐ์ž ์˜ค๋ฒ„๋กœ๋”ฉ์˜ ๋œ ์ œํ•œ๋œ ๋ฒ„์ „์„ ์š”๊ตฌํ•ฉ๋‹ˆ๋‹ค. (Getter์™€ setter๋Š” ์ด๋ฏธ ์—ฐ์‚ฐ์ž ์˜ค๋ฒ„๋กœ๋”ฉ์ž…๋‹ˆ๋‹ค.) ๊ทธ๋ฆฌ๊ณ  ๋‹ค๋ฅธ ์–ธ์–ด๋กœ ์—ฐ์‚ฐ์ž ์˜ค๋ฒ„๋กœ๋“œ๋ฅผ ์ฒ˜๋ฆฌํ•œ ์‚ฌ๋žŒ์œผ๋กœ์„œ ์ €๋Š” ๋Œ€๋ถ€๋ถ„์˜ ๊ฒฝ์šฐ ํ”ผํ•ด์•ผ ํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ๋ฌผ๋ก  ๋ˆ„๊ตฐ๊ฐ€๋Š” ๋ฐ์นด๋ฅดํŠธ ๋ฐ ๊ทน์ ๊ณผ ๊ฐ™์€ ์ˆ˜ํ•™์  ์˜ˆ์ œ๋ฅผ ์ œ์•ˆํ•  ์ˆ˜ ์žˆ์ง€๋งŒ TS๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋Œ€๋ถ€๋ถ„์˜ ๊ฒฝ์šฐ(์ด ์Šค๋ ˆ๋“œ์˜ ์˜ˆ์ œ ํฌํ•จ) ์—ฐ์‚ฐ์ž ์˜ค๋ฒ„๋กœ๋”ฉ์ด ํ•„์š”ํ•œ ๊ฒƒ์€ ์•„๋งˆ๋„ ์ฝ”๋“œ ๋ƒ„์ƒˆ์ผ ๊ฒƒ์ž…๋‹ˆ๋‹ค. API๋ฅผ ๋” ๋‹จ์ˆœํ•˜๊ฒŒ ๋งŒ๋“œ๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋ณด์ผ ์ˆ˜ ์žˆ์ง€๋งŒ ๊ทธ ๋ฐ˜๋Œ€์˜ ๊ฒฝํ–ฅ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์•ž์—์„œ ์–ธ๊ธ‰ํ–ˆ๋“ฏ์ด ๋‹ค์Œ์ด ๋ฐ˜๋“œ์‹œ ์‚ฌ์‹ค์ด ์•„๋‹Œ ๊ฒƒ์€ ๋งค์šฐ ํ˜ผ๋ž€์Šค๋Ÿฝ๊ณ  ์ง๊ด€์ ์ด์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

foo.x = y;
if (foo.x === y) { // this could be false?

(๋‚ด ์ƒ๊ฐ์— ํ•ฉ๋ฆฌ์ ์œผ๋กœ ๋ณด์ด๋Š” setter๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ๋Š” ๋กœ๊น…๊ณผ ๊ฐ์ฒด์— "dirty" ํ”Œ๋ž˜๊ทธ๋ฅผ ์„ค์ •ํ•˜์—ฌ ๋‹ค๋ฅธ ๊ฒƒ์ด ํ•„๋“œ๊ฐ€ ๋ณ€๊ฒฝ๋˜์—ˆ๋Š”์ง€ ์—ฌ๋ถ€๋ฅผ ์•Œ ์ˆ˜ ์žˆ๋„๋ก ์„ค์ •ํ•˜๋Š” ๊ฒฝ์šฐ๋ฟ์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ์ด ๋‘˜ ์ค‘ ์–ด๋Š ๊ฒƒ๋„ ์‹ค์ œ๋กœ ๊ณ„์•ฝ์„ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋ฌผ์ฒด.)

@MikeyBurkman

[...] ํ•˜์ง€๋งŒ TS๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋Œ€๋ถ€๋ถ„์˜ ๊ฒฝ์šฐ(์ด ์Šค๋ ˆ๋“œ์˜ ์˜ˆ์ œ ํฌํ•จ), ์—ฐ์‚ฐ์ž ์˜ค๋ฒ„๋กœ๋”ฉ์ด ํ•„์š”ํ•œ ๊ฒƒ์€ ์•„๋งˆ๋„ ์ฝ”๋“œ ๋ƒ„์ƒˆ๋ผ๊ณ  ์ฃผ์žฅํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. [...]

 foo.x = y; 
 if (foo.x === y) { // this could be false?

๋”ฐ๋ผ์„œ ์œ ํ˜•์ด ์ผ์น˜ํ•˜๋Š” ๊ฒƒ๋งŒ์œผ๋กœ๋Š” ๋†€๋ผ์šด ๋™์ž‘์„ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์—†์œผ๋ฉฐ ์‹ค์ œ๋กœ el.style.display = ''; //so is this now true: el.style.display === ''? ๋Š” ์ด๊ฒƒ์ด ์ด๋ก ์ ์ธ ๊ฒƒ๋„ ์•„๋‹˜์„ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค. ํ‰๋ฒ”ํ•œ ์˜ค๋ž˜๋œ ํ•„๋“œ์˜ ๊ฒฝ์šฐ์—๋„ NaN์— ๋Œ€ํ•ด์„œ๋Š” ๊ฐ€์ •์ด ์„ฑ๋ฆฝํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ ๋” ์ค‘์š”ํ•œ ๊ฒƒ์€ TS๊ฐ€ DOM๊ณผ ๊ฐ™์€ ์ฃผ์š” ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ํฌํ•จํ•˜์—ฌ ๊ธฐ์กด JS API์™€ ์ƒํ˜ธ ์šด์šฉํ•ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— TS๊ฐ€ ์ด๋Ÿฌํ•œ ์‚ฌํ•ญ์— ๋Œ€ํ•ด ์˜๊ฒฌ์„ ์ œ์‹œ ํ•  ์ˆ˜ ์—†๋‹ค๋Š” ์ ์„ ๋ฌด์‹œํ•œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ API๊ฐ€ ์ด์ƒ์ ์ธ์ง€ ์—ฌ๋ถ€๋Š” ์ค‘์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ค‘์š”ํ•œ ๊ฒƒ์€ TS๊ฐ€ ๊ทธ๋Ÿฌํ•œ ์ฃผ์–ด์ง„ API์™€ ๊น”๋”ํ•˜๊ฒŒ ์ƒํ˜ธ ์šด์šฉํ•  ์ˆ˜ ์—†๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด์ œ API๊ฐ€ ๋‚ด๋ถ€์ ์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ํด๋ฐฑ ๋…ผ๋ฆฌ๋ฅผ ๋‹ค์‹œ ๊ตฌํ˜„ํ•˜์—ฌ setter์— ์ „๋‹ฌ๋œ getter ์œ ํ˜• ์ด์™ธ์˜ ๊ฐ’์„ ๊ฐ•์ œ ์‹คํ–‰ํ•˜์—ฌ ์†์„ฑ์„ getter ์œ ํ˜•์œผ๋กœ ์ž…๋ ฅ ํ•˜๊ฑฐ๋‚˜ ์œ ํ˜• ๊ฒ€์‚ฌ๋ฅผ ๋ฌด์‹œํ•˜์—ฌ ์ถ”๊ฐ€ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ฐ getters ์‚ฌ์ดํŠธ์—์„œ ์“ธ๋ชจ์—†๋Š” ์œ ํ˜• ์–ด์„ค์…˜์„ ์‚ฌ์šฉํ•˜๋ฏ€๋กœ ์†์„ฑ์„ setters ์œ ํ˜•์œผ๋กœ ์ž…๋ ฅํ•˜์‹ญ์‹œ์˜ค. ๋˜๋Š” ๋” ๋‚˜์œ ๊ฒƒ์€ TS๊ฐ€ ์ด์ƒ์ ์ธ์ง€ ์—ฌ๋ถ€ ์— ๊ด€๊ณ„์—†์ด DOM์— ์ฃผ์„์„ ์ถ”๊ฐ€ํ•˜๊ธฐ ์œ„ํ•ด ์„ ํƒํ•˜๋Š” ๋ชจ๋“  ์ผ์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๊ทธ ์„ ํƒ์€ ๋ชจ๋‘ ๋‚˜์˜๋‹ค. ์ด๋ฅผ ํ”ผํ•˜๋Š” ์œ ์ผํ•œ ๋ฐฉ๋ฒ•์€ JS API๋ฅผ ๊ฐ€๋Šฅํ•œ ํ•œ ์ถฉ์‹คํ•˜๊ฒŒ ํ‘œํ˜„ํ•ด์•ผ ํ•  ํ•„์š”์„ฑ์„ ๋ฐ›์•„๋“ค์ด๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์—์„œ๋Š” ๊ฐ€๋Šฅํ•œ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค (์ด๋ฅผ ๊ฒฐ์ •์ ์œผ๋กœ ์ค‘์š”ํ•˜์ง€ ์•Š๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋Š” TS ๋‚ด๋ถ€์— ๋Œ€ํ•œ ์ง€์‹ ์—†์ด๋„).

๊ฐ€๋Šฅํ•œ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค(์ด๋ฅผ ๊ฒฐ์ •์ ์œผ๋กœ ์ค‘์š”ํ•˜์ง€ ์•Š๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋Š” TS ๋‚ด๋ถ€์— ๋Œ€ํ•œ ์ง€์‹ ์—†์ด๋Š” ์ธ์ •ํ•จ)

๋‚˜๋Š” ๊ทธ๋“ค์ด ๋” ์ตœ๊ทผ์— ํ™œ์„ฑํ™” ํ•œ ์ƒˆ๋กœ์šด ์œ ํ˜• ์„ ์–ธ ๊ตฌ๋ฌธ ์ค‘ ์ผ๋ถ€๊ฐ€ ์ด์ „์— ์‹คํ˜„ ๊ฐ€๋Šฅํ•˜์ง€ ์•Š์•˜์„ ๋•Œ ์ด๊ฒƒ์„ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•˜๋ฏ€๋กœ ์ด ๋ฌธ์ œ๋ฅผ ๋‹ค์‹œ ์—ฌ๋Š” ๊ฒƒ์„ ์‹ค์ œ๋กœ ๊ณ ๋ คํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค... @RyanCavanaugh

์ด์ƒ์ ์ธ ์„ธ๊ณ„์—์„œ TS๋Š” ๋ชจ๋“  JS API์™€ ์ƒํ˜ธ ์šด์šฉ๋ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๊ทธ๋ ‡์ง€ ์•Š์Šต๋‹ˆ๋‹ค. TS์— ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์ž…๋ ฅํ•  ์ˆ˜ ์—†๋Š” ๋งŽ์€ JS ๊ด€์šฉ๊ตฌ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๋‚˜๋Š” ๊ทธ๋“ค์ด ๋” ๋‚˜์œ ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ์‹ค์ œ๋กœ ๋” ๋‚˜์€ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๊ด€์šฉ๊ตฌ๋กœ ์ด์–ด์ง€๋Š” ๊ฒƒ์„ ์ˆ˜์ •ํ•˜๋Š” ๋ฐ ์ง‘์ค‘ํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์„ ์ œ์ •์‹ ์œผ๋กœ ์ง€์›ํ•˜๋Š” ๊ฒƒ๋„ ์ข‹์ง€๋งŒ, ๊ฐœ์ธ์ ์œผ๋กœ ์ œํ•œ๋œ ์‹œ๊ฐ„์„ ๋จผ์ € ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค ํ›จ์”ฌ ๋” ์ข‹์€ 12๊ฐ€์ง€๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ๊ทธ ๋ชฉ๋ก์—์„œ ํ›จ์”ฌ ์•„๋ž˜์— ์žˆ์Šต๋‹ˆ๋‹ค.

@MikeyBurkman ์šฐ์„ ์ˆœ์œ„ ์งˆ๋ฌธ์€ ์œ ํšจํ•ฉ๋‹ˆ๋‹ค. ์ œ ์ฃผ์š” ๊ด€์‹ฌ์‚ฌ๋Š” @RyanCavanaugh ๊ฐ€ ์ด ๋ฌธ์ œ๋ฅผ ์ข…๋ฃŒํ•˜๊ณ  ์‚ญ์ œํ•˜๊ธฐ๋กœ ํ•œ ๊ฒฐ์ •์ž…๋‹ˆ๋‹ค. ์ด ์Šค๋ ˆ๋“œ์—์„œ ์ง€์ ํ•œ ๋ชจ๋“  ๋ฌธ์ œ๋ฅผ ๋ฌด์‹œํ•˜๋Š” ๊ฒƒ์€ Typescript์˜ ๋ช…์‹œ๋œ ์‚ฌ๋ช…๊ณผ ์ง์ ‘์ ์œผ๋กœ ์ถฉ๋Œํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” Javascript์˜ "์ƒ์œ„ ์ง‘ํ•ฉ"(ํ•˜์œ„ ์ง‘ํ•ฉ ๋Œ€์‹ )์ด ๋˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์˜ˆ, ์ด ๋ฌธ์ œ๋Š” _์•„๋งˆ๋„_ ๊ฒฐ๊ตญ ์ˆ˜์ •๋˜์–ด์•ผ ํ•˜๋Š” ๋ฌธ์ œ์ด๊ธฐ ๋•Œ๋ฌธ์— ์ด ๋ฌธ์ œ๊ฐ€ ์ข…๋ฃŒ๋˜์–ด์„œ๋Š” ์•ˆ ๋œ๋‹ค๋Š” ๋ฐ ๋™์˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. (์‚ฌ์‹ค ๊ทธ๋ ‡๊ฒŒ ๋ ์ง€๋Š” ์˜๋ฌธ์ด์ง€๋งŒ.)

์ด๊ฒƒ์„ ์ œ์ •์‹ ์œผ๋กœ ์ง€์›ํ•˜๋Š” ๊ฒƒ๋„ ์ข‹์ง€๋งŒ, ๊ฐœ์ธ์ ์œผ๋กœ ์ œํ•œ๋œ ์‹œ๊ฐ„์„ ์šฐ์„ ์ ์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค ๋” ๋‚˜์€ ์ˆ˜์‹ญ ๊ฐ€์ง€๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ธฐ์กด DOM API์™€ ๊ธฐ์กด JS API๋ฅผ ๋” ์•ˆ์ „ํ•˜๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ด์ค€๋‹ค๋Š” ์ ์—์„œ TypeScript์˜ ์ค‘์š”ํ•œ ์ธก๋ฉด์„ ๊ณผ์†Œํ‰๊ฐ€ํ•˜๊ณ  ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๊ฒƒ์€ ๊ฑฐํ’ˆ ๋‚ด์—์„œ ์ž์‹ ์˜ ์ฝ”๋“œ ์ด์ƒ์„ ์•ˆ์ „ํ•˜๊ฒŒ ์œ ์ง€ํ•˜๊ธฐ ์œ„ํ•ด ์กด์žฌํ•ฉ๋‹ˆ๋‹ค.

๋‚ด ๊ด€์ ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค. ๊ตฌ์„ฑ ์š”์†Œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ๋นŒ๋“œํ•˜๊ณ , ๋‚ด druthers์—๊ฒŒ ์ฃผ์–ด์ง„ setter/getter ๊ฐ„์˜ ๋ถˆ์ผ์น˜๋ฅผ ์˜๋„์ ์œผ๋กœ ๋ฐœ์ƒ์‹œํ‚ค์ง€๋Š” ์•Š์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋•Œ๋•Œ๋กœ ๋‚ด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ์ œ์ž๋ฆฌ์—์„œ ๋‹ค๋ฅธ ์‹œ์Šคํ…œ๊ณผ ์ธํ„ฐํŽ˜์ด์Šคํ•ด์•ผ ํ•˜๋Š” ๋ฐฉ์‹์— ๋”ฐ๋ผ ๊ฐ•์ œ๋กœ ์†์„ ๋—๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด Angular๋Š” ๋Œ€์ƒ ์œ ํ˜•์— ๋Œ€ํ•œ ์ง€์‹์„ ๊ธฐ๋ฐ˜์œผ๋กœ ์œ ํ˜• ๊ฐ•์ œ ๋ณ€ํ™˜์„ ์ˆ˜ํ–‰ํ•˜๊ธฐ๋ณด๋‹ค๋Š” ๋งˆํฌ์—…์—์„œ ์˜ค๋Š” ๊ตฌ์„ฑ ์š”์†Œ์˜ ๋ชจ๋“  ์ž…๋ ฅ ์†์„ฑ์„ ๋ฌธ์ž์—ด๋กœ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค(์ตœ์†Œํ•œ ๋งˆ์ง€๋ง‰์œผ๋กœ ํ™•์ธํ•จ). ๊ทธ๋ž˜์„œ, ๋‹น์‹ ์€ ๋ฌธ์ž์—ด์„ ๋ฐ›์•„๋“ค์ด๊ธฐ๋ฅผ ๊ฑฐ๋ถ€ํ•ฉ๋‹ˆ๊นŒ? ์œ ํ˜•์„ ์‚ฌ์šฉํ•˜๊ธฐ ๋”์ฐํ•˜๊ฒŒ ๋งŒ๋“ค๋”๋ผ๋„ ๋ชจ๋“  ๊ฒƒ์„ ๋ฌธ์ž์—ด๋กœ ๋งŒ๋“œ์‹ญ๋‹ˆ๊นŒ? ์•„๋‹ˆ๋ฉด TypeScript๊ฐ€ ์‹œํ‚ค๋Š” ๋Œ€๋กœ ํ•˜๊ณ  ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์œ ํ˜•์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๊นŒ? string | ์ƒ‰์ƒ์„ ์ง€์ •ํ•˜์ง€๋งŒ ๊ฒŒํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋”์ฐํ•ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ๋“ค์€ ๋ชจ๋‘ ํƒ€์ž… ์‹œ์Šคํ…œ์˜ ์•ฝ๊ฐ„์˜ ์ถ”๊ฐ€ ํ‘œํ˜„์ด ๋„์›€์ด ๋˜์—ˆ์„ ๋•Œ ์•ˆ์ „์„ฑ์„ ๊ฐ์†Œ์‹œํ‚ค๋Š” ๋งค์šฐ ๋”์ฐํ•œ ์˜ต์…˜์ž…๋‹ˆ๋‹ค.

๋ฌธ์ œ๋Š” ์ด๋Ÿฌํ•œ ๋ฌธ์ œ๋ฅผ ์ผ์œผํ‚ค๋Š” ๊ฒƒ์ด Angular๋งŒ์ด ์•„๋‹ˆ๋ผ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. Angular๋Š” ์†์„ฑ ์ง‘ํ•ฉ์—์„œ ์ž๋™ ๊ฐ•์ œ ๋ณ€ํ™˜์ด ๋ฐœ์ƒํ•˜๋Š” DOM์˜ ๋งŽ์€ ์‹œ๋‚˜๋ฆฌ์˜ค๋ฅผ ๋ฐ˜์˜ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ด๋Ÿฌํ•œ ์ƒํ™ฉ์—์„œ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•˜์ง€๋งŒ getter๋Š” ํ•ญ์ƒ ์˜ˆ์ƒ๋˜๋Š” ๋‹จ์ผ ์œ ํ˜•์ž…๋‹ˆ๋‹ค.

๋‚˜์—๊ฒŒ ๊ทธ๊ฒƒ์€ ์ผ๋ฐ˜์ ์œผ๋กœ ํ‚ค-๊ฐ’ ์Œ์„ ์ €์žฅํ•  ์ˆ˜ ์žˆ๋Š” ์ผ๋ถ€ ๋ฒ”์šฉ ์ €์žฅ์†Œ ์ฃผ์œ„์— ๋ž˜ํผ๋ฅผ ๋งŒ๋“ค๊ณ  ์‚ฌ์šฉ์ž๋ฅผ ํŠน์ • ํ‚ค๋กœ ์ œํ•œํ•˜๋ ค๋Š” ๊ฒฝ์šฐ์˜ ๋ฌธ์ œ์ž…๋‹ˆ๋‹ค.

class Store {
  private dict: Map<string, any>;

  get name(): string | null {
    return this.dict.get('name') as string | null;
  }

  set name(value: string) {
    this.dict.set('name', value);
  }
}

๊ฐ’์ด ์ด์ „์— ์„ค์ •๋˜์ง€ ์•Š์•˜์ง€๋งŒ null ๋กœ ์„ค์ •ํ•  ์ˆ˜ ์—†๋Š” ๊ฒฝ์šฐ ์‚ฌ์šฉ์ž๋Š” null ๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ˜„์žฌ๋กœ์„œ๋Š” setter ์ž…๋ ฅ ์œ ํ˜•์— null ๊ฐ€ ํฌํ•จ๋˜์–ด์•ผ ํ•˜๋ฏ€๋กœ ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

@fan-tom, ์ด ๋ฌธ์ œ๋ฅผ ๋‹ค์‹œ ์—ด์–ด์•ผ ํ•˜๋Š” ์ด์œ ์— ๋Œ€ํ•œ ํ›Œ๋ฅญํ•œ ์‚ฌ์šฉ ์‚ฌ๋ก€์ž…๋‹ˆ๋‹ค! ๊ณ„์† ์˜ค์„ธ์š”.

์ด ๋ฌธ์ œ๋Š” ๋งค์šฐ ๋†’์€ ํˆฌํ‘œ ์ˆ˜๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค!

์ด๊ฒƒ์€ TSํŒ€์˜ ํ”„๋กœ์ ํŠธ์ด๊ธฐ ๋•Œ๋ฌธ์— ์›ํ•˜๋Š” ๋Œ€๋กœ ๋งˆ์Œ๊ป ์ฆ๊ธธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์™ธ๋ถ€ ์‚ฌ์šฉ์ž ์ปค๋ฎค๋‹ˆํ‹ฐ์— ์ด ๊ธฐ๋Šฅ์„ ์ตœ๋Œ€ํ•œ ์œ ์šฉํ•˜๊ฒŒ ๋งŒ๋“œ๋Š” ๊ฒƒ์„ ๋ชฉํ‘œ๋กœ ํ•œ๋‹ค๋ฉด TS ํŒ€์ด ์ปค๋ฎค๋‹ˆํ‹ฐ์˜ ๋†’์€ ํˆฌํ‘œ ์ˆ˜๋ฅผ ๊ฐ•๋ ฅํ•˜๊ฒŒ ๊ณ ๋ คํ•  ์ˆ˜ ์žˆ๊ธฐ๋ฅผ ๋ฐ”๋ž๋‹ˆ๋‹ค.

typescriptlang.org์˜ ํ™ˆํŽ˜์ด์ง€๋Š” ํ˜„์žฌ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ •ํ™•ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

TypeScript๋Š” ์ผ๋ฐ˜ JavaScript๋กœ ์ปดํŒŒ์ผ๋˜๋Š” JavaScript์˜ ์œ ํ˜•์ด ์ง€์ •๋œ ์ƒ์œ„ ์ง‘ํ•ฉ ์ž…๋‹ˆ๋‹ค.

TypeScript๋Š” ์ผ๋ฐ˜ JavaScript๋กœ ์ปดํŒŒ์ผ๋˜๋Š” JavaScript _subset_์˜ ์œ ํ˜•์ด ์ง€์ •๋œ _superset_์ž…๋‹ˆ๋‹ค. : ์Šค๋งˆ์ผ :

TypeScript๋Š” ์ผ๋ฐ˜ JavaScript๋กœ ์ปดํŒŒ์ผ๋˜๋Š” JavaScript ํ•˜์œ„ ์ง‘ํ•ฉ์˜ ์œ ํ˜•์ด ์ง€์ •๋œ ์ƒ์œ„ ์ง‘ํ•ฉ์ž…๋‹ˆ๋‹ค.

์ข€ ๋” ์™ธ๊ต์ ์œผ๋กœ ๋งํ•˜์ž๋ฉด, ํŒ€์ด ์œ ํ˜• ์‹œ์Šคํ…œ ๋ชจ๋ธ๋ง์—์„œ ์ด๋Ÿฐ ์ข…๋ฅ˜์˜ ๋…๋‹จ์ ์ธ ์ƒ๋žต์„ ํ•  ๋•Œ JavaScript์˜ ๋…๋‹จ์ ์ธ ์ƒ์œ„ ์ง‘ํ•ฉ์ด๋ผ๊ณ  ๋งํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋“ค์€ "์šฐ๋ฆฌ๊ฐ€ ํ•˜๊ธฐ ์–ด๋ ต๊ธฐ ๋•Œ๋ฌธ์— ์šฐ๋ฆฌ๋Š” ์ด๊ฒƒ์„ ๋ชจ๋ธ๋งํ•˜์ง€ ์•Š์„ ๊ฒƒ์ด๋ฉฐ, ์–ด์จŒ๋“  ๋‹น์‹ ์ด ํ•ด์„œ๋Š” ์•ˆ ๋œ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค"๋ผ๊ณ  ๋งํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ JavaScript๋Š” _ํ•ด์„œ๋Š” ์•ˆ ๋˜๋Š”_ ์ผ๋“ค๋กœ ๊ฐ€๋“ ์ฐจ ์žˆ์œผ๋ฉฐ ์ผ๋ฐ˜์ ์œผ๋กœ Typescript๋Š” ์˜์ง€์™€ ๋…ธํ•˜์šฐ๊ฐ€ ์žˆ๋‹ค๋ฉด ์ด๋Ÿฌํ•œ ์ผ์„ ํ•˜๋Š” ๊ฒƒ์„ ์ฐจ๋‹จํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์™œ๋ƒํ•˜๋ฉด ์ผ๋ฐ˜์ ์ธ ์ „๋žต์€ JavaScript์— ๋Œ€ํ•ด ๋…๋‹จ์ ์ด์ง€ ์•Š๋Š” ๊ฒƒ ๊ฐ™๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. Typescript๋กœ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๊ณ  ์‹คํ–‰ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

์ด๊ฒƒ์ด API๊ฐ€ setter ๊ธฐ๋ฐ˜ ๊ฐ•์ œ ๋ณ€ํ™˜์„ ์ˆ˜ํ–‰ํ•˜์ง€ ์•Š์•„์•ผ ํ•œ๋‹ค๋Š” ๋ฏฟ์Œ์„ ์ธ์šฉํ•˜๋ฉด์„œ ์ด ์ผ๋ฐ˜์ ์ธ(DOM์—์„œ ์‚ฌ์šฉ๋˜๋Š”) ์‹œ๋‚˜๋ฆฌ์˜ค๋ฅผ ๋ชจ๋ธ๋งํ•˜๋Š” ๊ฒƒ์„ ๊ฑฐ๋ถ€ํ•˜๋Š” ๊ฒƒ์ด ์ด์ƒํ•œ ์ด์œ ์ž…๋‹ˆ๋‹ค.

ํ˜„์žฌ ์ด๊ฒƒ์€ ๋ถˆ๊ฐ€๋Šฅํ•œ ๊ฒƒ ๊ฐ™์œผ๋ฉฐ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

class MyClass {

    private _myDate: moment.Moment;

    get myDate(): moment.Moment {
        return this._myDate;
    }

    set myDate(value: moment.Moment) {
        assert.fail('Setter for myDate is not available. Please use: setMyDate() instead');
    }

    setMyDate(value: Date | moment.Moment) {
        this._myDate = moment(value);
    }
}

๋‹น์‹ ์ด ํ•  ์ˆ˜ ์žˆ๋Š” ์ตœ์„ ์€ ์ƒ์„ฑ์ž๋ฅผ ์ถ”๊ฐ€ํ•˜๊ณ  ๊ฑฐ๊ธฐ์—์„œ ์ปค์Šคํ…€ setter ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋งŒ์•ฝ ๊ทธ๊ฒƒ์ด ๋‹น์‹ ์ด ๊ทธ ๊ฐ’์„ ์„ค์ •ํ•˜๋Š” ์œ ์ผํ•œ ์‹œ๊ฐ„์ด๋ผ๋ฉด.

constructor(value: Date | moment.Moment) {
    this.setMyDate(value);
}

๊ฐ’์„ ์ง์ ‘ ํ• ๋‹นํ•  ๋•Œ์˜ ๋ฌธ์ œ๋Š” ์—ฌ์ „ํžˆ ๋‚จ์•„ ์žˆ์Šต๋‹ˆ๋‹ค.

5.5๋…„์ด ์ง€๋‚œ ํ›„ ์ด์— ๋Œ€ํ•œ ์—…๋ฐ์ดํŠธ๊ฐ€ ์žˆ์Šต๋‹ˆ๊นŒ?

@xhliu ๋Š” ๋ ˆ์ด๋ธ”์—์„œ ์•Œ ์ˆ˜ ์žˆ๋“ฏ์ด ๋„ˆ๋ฌด ๋ณต์žกํ•˜์—ฌ ํ•ด๊ฒฐํ•˜๊ธฐ ์–ด๋ ค์šด ์„ค๊ณ„ ์ œํ•œ ์‚ฌํ•ญ์ด๋ฏ€๋กœ ๋ฌธ์ œ๊ฐ€ ์ข…๋ฃŒ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๋‚˜๋Š” ์—…๋ฐ์ดํŠธ๋ฅผ ๊ธฐ๋Œ€ํ•˜์ง€ ์•Š์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋‹ซํžŒ ๋ฌธ์ œ์˜ ์‹œ๊ฐ„ ๊ธธ์ด๋Š” ์ผ์ข…์˜ ๊ด€๋ จ์ด ์—†์Šต๋‹ˆ๋‹ค.

๋‹ค์‹œ ์—ด์–ด์ฃผ์„ธ์š”. ๋˜ํ•œ ์ด๊ฒƒ์€ ์ธํ„ฐํŽ˜์ด์Šค ์ˆ˜์ค€์—์„œ ์ถ”๊ฐ€๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ณ ์ „์ ์ธ ์˜ˆ๋Š” ์ฝ๊ณ  ์“ธ ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์— ๋Œ€ํ•ด ์™„์ „ํ•œ ์œ ์—ฐ์„ฑ์ด ์žˆ๋Š” ํ”„๋ก์‹œ๋ฅผ ๊ตฌํ˜„ํ•  ๋•Œ์ž…๋‹ˆ๋‹ค.

@xhliu ... ๋„ˆ๋ฌด ๋ณต์žกํ•ด์„œ ๋‹ค๋ฃจ๊ธฐ ์–ด๋ ต์Šต๋‹ˆ๋‹ค...

https://ts-ast-viewer.com/#code/MYewdgzgLgBFCm0DyAjAVjAvDA3gKBkJgDMQQAuGAIhQEManKvAXzzwWXQDpSQg

const testObj = {
    foo: "bar"
}

testObj.foo

๊ธฐํ˜ธ foo๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋งํ•ฉ๋‹ˆ๋‹ค.

  foo
    flags: 4
    escapedName:"foo"
    declarations: [
      PropertyAssignment (foo)
    ]
    valueDeclaration: PropertyAssignment (foo)

์—ฌ๊ธฐ์—๋Š” ์ถ”๊ฐ€ ์ •๋ณด๋ฅผ ์œ„ํ•œ ๊ณต๊ฐ„์ด ๋งŽ์ด ์žˆ์œผ๋ฉฐ ์ด๋Š” TS๋ฅผ ์œ„ํ•œ ํ›Œ๋ฅญํ•œ ๋””์ž์ธ์ž…๋‹ˆ๋‹ค. ์ด๊ฒƒ์„ ์„ค๊ณ„ํ•œ ์‚ฌ๋žŒ์€ ์•„๋งˆ๋„ ๋ฏธ๋ž˜์— ์ถ”๊ฐ€ ๊ธฐ๋Šฅ(์‹ฌ์ง€์–ด ํฐ ๊ธฐ๋Šฅ๋„ ํฌํ•จ)์„ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•˜๊ธฐ ์œ„ํ•ด ํŠน๋ณ„ํžˆ ๊ทธ๋ ‡๊ฒŒ ํ–ˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ด ์‹œ์ ๋ถ€ํ„ฐ ์ถ”์ธก:

์˜์‚ฌ ์ฝ”๋“œ ์˜ˆ์ œ์˜ ๊ฒฝ์šฐ accessDelclaration: AccessSpecification (foo) ๋ฅผ ์„ ์–ธํ•  ์ˆ˜ ์žˆ์œผ๋ฉด foo ๊ธฐํ˜ธ์™€ ํ•ด๋‹น ์„ ์–ธ์„ ์ธ์‹ํ•˜๋Š” PropertyAccessExpression ๊ฐ€ "accessDelclaration" ๋ฐ ๋Œ€์‹  ์ž…๋ ฅ์„ ์‚ฌ์šฉํ•˜์‹ญ์‹œ์˜ค.

accessDelclaration ์†์„ฑ์„ "foo" ๊ธฐํ˜ธ์— ์ถ”๊ฐ€ํ•˜๋Š” ๊ตฌ๋ฌธ์ด ์žˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•˜๋ฉด PropertyAccessExpression์€ ts.createIdentifier("foo") ์—์„œ ๊ฐ€์ ธ์˜ค๋Š” ๊ธฐํ˜ธ์—์„œ "AccessSpecification"์„ ๊ฐ€์ ธ์™€์„œ ๋‹ค๋ฅธ ์œ ํ˜•์„ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

ts.createPropertyAccess(
  ts.createIdentifier("testObj"),
  ts.createIdentifier("foo")
)

์ถ”์ธก์ปจ๋Œ€, ์ด ๋ฌธ์ œ์˜ ๊ฐ€์žฅ ์–ด๋ ค์šด ๋ถ€๋ถ„์€ ๊ตฌ๋ฌธ(๋˜๋Š” ์•„๋งˆ๋„ ํšŒ์‚ฌ ์ฒ ํ•™?)๊ณผ ๊ด€๋ จ๋œ ์ž์ „๊ฑฐ ์‚ฌ๊ณ ์˜ ์–‘์ผ ๊ฐ€๋Šฅ์„ฑ์ด ๋†’์ง€๋งŒ ๊ตฌํ˜„ ๊ด€์ ์—์„œ๋Š” ๋„๊ตฌ๊ฐ€ ๋ชจ๋‘ ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ts.createPropertyAccess() ํ•จ์ˆ˜์— ๋‹จ์ผ ์กฐ๊ฑด์ด ์ถ”๊ฐ€๋˜๊ณ  ํ•ด๋‹น ์กฐ๊ฑด๊ณผ ๊ทธ ํšจ๊ณผ๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ์„ ์–ธ ํด๋ž˜์Šค๊ฐ€ ๊ฐœ์ฒด ์†์„ฑ์˜ ๊ธฐํ˜ธ์— ์ถ”๊ฐ€๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์ด๊ฒƒ์ด ์ ˆ์‹คํžˆ ํ•„์š”ํ•œ ์ด์œ (ํŠนํžˆ DOM ๋ฐ Angular์˜ ๊ฒฝ์šฐ)์— ์ข‹์€ ์˜ˆ๊ฐ€ ๋งŽ์ด ์ž‘์„ฑ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

string ๋ฅผ window.location ์— ํ• ๋‹นํ•˜๋Š” ๊ฒƒ์ด ์ž‘๋™ํ•˜์ง€ ์•Š๊ณ  as any ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์„ ์ˆ˜ํ–‰ํ•ด์•ผ ํ•˜๋Š” TS๋กœ ์ด์ „ JS ์ฝ”๋“œ๋ฅผ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ํ•  ๋•Œ ์˜ค๋Š˜ ์ด ๋ฌธ์ œ๋ฅผ ๊ฒช์—ˆ์Šต๋‹ˆ๋‹ค. ๐Ÿ˜Ÿ

Window.location ์ฝ๊ธฐ ์ „์šฉ ์†์„ฑ์€ ๋ฌธ์„œ์˜ ํ˜„์žฌ ์œ„์น˜์— ๋Œ€ํ•œ ์ •๋ณด๊ฐ€ ํฌํ•จ๋œ Location ๊ฐœ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

Window.location์€ ์ฝ๊ธฐ ์ „์šฉ Location ๊ฐ์ฒด์ด์ง€๋งŒ ์—ฌ๊ธฐ์— DOMString์„ ํ• ๋‹นํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ๋Œ€๋ถ€๋ถ„์˜ ๊ฒฝ์šฐ ์œ„์น˜๊ฐ€ ๋ฌธ์ž์—ด์ธ ๊ฒƒ์ฒ˜๋Ÿผ ์ž‘์—…ํ•  ์ˆ˜ ์žˆ์Œ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. location = ' http://www.example.com '์€ location.href = ' http://www.example.com '์˜ ๋™์˜์–ด์ž…๋‹ˆ๋‹ค. .
์›์ฒœ

string ๋ฅผ window.location ์— ํ• ๋‹นํ•˜๋Š” ๊ฒƒ์ด ์ž‘๋™ํ•˜์ง€ ์•Š๊ณ  as any ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์„ ์ˆ˜ํ–‰ํ•ด์•ผ ํ•˜๋Š” TS๋กœ ์ด์ „ JS ์ฝ”๋“œ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜

์ข‹์€ ์˜ˆ์ž…๋‹ˆ๋‹ค.

TS๋Š” ์ด๊ฒƒ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ JavaScript์˜ ๋งค์šฐ ์ •์ƒ์ ์ธ ๋ถ€๋ถ„์ž…๋‹ˆ๋‹ค.

ํ˜„์žฌ ๋ฌธ์ œ๊ฐ€ ์ข…๋ฃŒ๋˜์—ˆ์Œ์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ๋ฐ ์ œ๊ฐ€ ์•Œ๊ธฐ๋กœ๋Š” ์ด ๊ธฐ๋Šฅ์ด ์‹คํ˜„๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๊นŒ?

@AGluk , ์ด ๋ฌธ์ œ๋ฅผ ๋‹ค์‹œ ์—ด์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์ด ํŽ˜์ด์ง€๊ฐ€ ๋„์›€์ด ๋˜์—ˆ๋‚˜์š”?
0 / 5 - 0 ๋“ฑ๊ธ‰