class ์์ฑ ์์ TypeScript์ ํด๋์ค ๋ฌธ๋ฒ๊ณผ JavaScript์ ๋ฌธ๋ฒ์ ๋น๊ตํด๋ณด์.
#
JS ํด๋์ค ๋ฌธ๋ฒJS์์ ํด๋์ค๋ ๋ค์๊ณผ ๊ฐ์ ๋ฌธ๋ฒ์ ์ฌ์ฉํ๋ค.
class MyClass { publicProp = 'value'; // public ํ๋กํผํฐ #privateProp = 'value'; // private ํ๋กํผํฐ. ES2019 ๋ถํฐ ์ง์. _protectedProp = 'value'; // protected ํ๋กํผํฐ. ๊ธฐ๋ฅ์ ์ผ๋ก ์ง์ํ์ง ์์ง๋ง, ๊ด๋ก์ ์ผ๋ก _๋ฅผ ์ฌ์ฉํ์ฌ ํํํ๊ณ ์ฝ์ํ์ฌ ์ฌ์ฉํจ.
constructor(...) { // ์์ฑ์ ๋ฉ์๋๋ก ๋งค๊ฐ๋ณ์ ๊ฐ์ ๋ฐ์ ํ๋กํผํฐ๋ฅผ ์ค์ ํ๊ฒ ํ ์ ์๋ค. // ... }
static staticMethod(...) {} // static ๋ฉ์๋
publicMethod(...) {} // public ๋ฉ์๋ #privateMethod(...) {} // private ๋ฉ์๋
get publicProp(...) {} // getter ๋ฉ์๋ set publicProp(...) {} // setter ๋ฉ์๋
get privateProp(...) {} // getter ๋ฉ์๋ set privateProp(...) {} // setter ๋ฉ์๋
get protectedProp(...) {} // getter ๋ฉ์๋ set protectedProp(...) {} // setter ๋ฉ์๋}
#
ํด๋์ค ์์JS์์๋ ํด๋์ค ์์์ ์ง์ํ๊ธฐ ๋๋ฌธ์, ๊ธฐ์กด ํด๋์ค๋ฅผ ํ์ฅํ์ฌ ํด๋์ค๋ฅผ ์์ฑํ ์์๋ค.
class Animal { constructor(name) { this.speed = 0; this.name = name; } run(speed) { this.speed = speed; alert(`${this.name} ์/๋ ์๋ ${this.speed}๋ก ๋ฌ๋ฆฝ๋๋ค.`); } stop() { this.speed = 0; alert(`${this.name} ์ด/๊ฐ ๋ฉ์ท์ต๋๋ค.`); }}
let animal = new Animal('๋๋ฌผ');
class Rabbit extends Animal { hide() { alert(`${this.name} ์ด/๊ฐ ์จ์์ต๋๋ค!`); }}
let rabbit = new Rabbit('ํฐ ํ ๋ผ');
rabbit.run(5); // ํฐ ํ ๋ผ ์/๋ ์๋ 5๋ก ๋ฌ๋ฆฝ๋๋ค.rabbit.hide(); // ํฐ ํ ๋ผ ์ด/๊ฐ ์จ์์ต๋๋ค!
ํด๋์ค Rabbit
์ผ๋ก ๋ง๋ ๊ฐ์ฒด๋ rabbit.hide()
์ ๊ฐ์ Rabbit
์ ์ ์๋ ๋ฉ์๋์๋ ์ ๊ทผํ ์ ์๊ณ , rabbit.run()
๊ณผ ๊ฐ์ Animal
์ ์ ์๋ ๋ฉ์๋์๋ ์ ๊ทผํ ์์๋ค.
extends
ํค์๋๋ ์ด๋ ๊ฒ ํ๋กํ ํ์
๊ธฐ๋ฐ์ผ๋ก ๋์ํ์ฌ, ๊ฐ์ฒด rabbit
-> Rabbit.prototype
-> Animal.prototype
์์ผ๋ก ๋ฉ์๋๋ฅผ ์ฐพ์์ ์คํํ๋ค.
#
์ ๊ทผ ์ ์ด์(Access Modifier)๊ฐ์ฒด ์งํฅ ํ๋ก๊ทธ๋๋ฐ์์๋ ์ ๊ทผ ์ ์ด์๋ฅผ ํ์ฉํด ๋ด๋ถ ์ธํฐํ์ด์ค์ ์ธ๋ถ ์ธํฐํ์ด์ค๋ฅผ ๊ตฌ๋ถํ์ฌ ์บก์ํํ๋ค.
public
: ์ด๋์๋ ์ง ์ ๊ทผํ ์ ์์ผ๋ฉฐ ์ธ๋ถ ์ธํฐํ์ด์ค๋ฅผ ๊ตฌ์ฑํ๋ค.protected
: ํด๋์ค ์์ ๊ณผ ์์ ํด๋์ค์์๋ง ์ ๊ทผํ ์ ์์ผ๋ฉฐ ๋ด๋ถ ์ธํฐํ์ด์ค๋ฅผ ๊ตฌ์ฑํ๋ค.private
: ํด๋์ค ์์ ์์๋ง ์ ๊ทผํ ์ ์์ผ๋ฉฐ ๋ด๋ถ ์ธํฐํ์ด์ค๋ฅผ ๊ตฌ์ฑํ๋ค.
JS์์๋ public
, protected
์ ๋ํ ๋ฌธ๋ฒ์ ์ง์์ด ์์ผ๋ฉฐ, ๊ด์ต์ ์ผ๋ก _
์ ๋์ฌ๋ฅผ ์ฌ์ฉํ์ฌ protected
ํ๋กํผํฐ๋ฅผ ์ฌ์ฉํ๋ค.
private
์์ฑ์ ES2019๋ถํฐ ์ง์ํ๊ฒ ๋์๋ค.
static
#
์ ์ ํ๋กํผํฐ์ ๋ฉ์๋๋ ์ด๋ค ํน์ ํ ๊ฐ์ฒด๊ฐ ์๋ ํด๋์ค์ ์ํ ํจ์๋ฅผ ๊ตฌํํ๊ณ ์ํ ๋ ์ฃผ๋ก ์ฌ์ฉ๋๋ค.
์ ์ ๋ฉค๋ฒ๋ ์์๋๋ค.
class Article { constructor(title, date) { this.title = title; this.date = date; }
static createTodays() { // this๋ Article์
๋๋ค. return new this("Today's digest", new Date()); }}
let article = Article.createTodays();
alert(article.title); // Today's digest
#
TS ํด๋์ค ๋ฌธ๋ฒTS๋ JS์ ๋ชจ๋ ํด๋์ค ๋ฌธ๋ฒ์ ์ง์ํ๋ฉฐ, ๊ทธ์ ๋ํด์ ๋ช ๊ฐ์ง ๋ฌธ๋ฒ์ ์ธ ์ง์์ ์ถ๊ฐํด์ค๋ค. ํ์ง๋ง ๋ชจ๋ ๋ฌธ๋ฒ์ ์ปดํ์ผ ํ์์ ๋ํด์๋ง ์ ์ฉ๋๊ณ , ๋ฐํ์์๋ ๊ฒฐ๊ตญ JS๊ฐ์ง์ํ๋ ๊ธฐ๋ฅ๋ง์ ์ฌ์ฉํด ๋์ํ๋ค๋ ๊ฒ์ ๊ธฐ์ตํ์.
๋ค์์ JS์์ ์ง์ํ์ง ์์ง๋ง, TS์์ ์ฌ์ฉํ ์ ์๋ Class์ ๊ด๋ จ๋ ๊ธฐ๋ฅ๋ค์ด๋ค.
readonly
#
ํ๋์๋ readonly
์ ์ด์๋ฅผ ์ ๋์ฌ๋ก ์ฌ์ฉํ ์ ์๋ค. ์ด๋ ๊ฒ ํ๋ฉด ์์ฑ์ ํจ์๊ฐ์๋ ๊ณณ์์ ํ ๋น์ ๋ฐฉ์งํ ์ ์๋ค.
class Greeter { readonly name: string = 'world';
constructor(otherName?: string) { if (otherName !== undefined) { this.name = otherName; } }
err() { this.name = 'not ok'; // Cannot assign to 'name' because it is a read-only property. }}const g = new Greeter();g.name = 'also not ok';// Cannot assign to 'name' because it is a read-only property.
overload
#
JS๋ ํจ์์ ๋งค๊ฐ๋ณ์์ ๊ฐฏ์์ ์๋ฃํ์ด ์์ ๋กญ๊ธฐ ๋๋ฌธ์, ์ค๋ฒ๋ก๋์ ๋ํ ๊ฐ๋ ์ด์ฌ์ค์ ์๋ค. (๋จ์ง, ๋งค๊ฐ๋ณ์์ ์กฐ๊ฑด์ ๋ฐ๋ฅธ ๋ถ๊ธฐ๋ฅผ ์์ฑํ๋ ์ ๋)
TS์์๋ ๋ค์ํ ๋ฐฉ์์ผ๋ก ํธ์ถํ ์ ์๋ ํจ์์ ๋ํด ๊ตฌ์ฒด์ ์ผ๋ก ์ค๋ฒ๋ก๋ signature
๋ฅผ ์์ฑํ ์ ์๋ค.
class Point { // Overloads constructor(x: number, y: string); constructor(s: string); constructor(xs: any, y?: any) { // TBD }}
class Util { // Overloads len(s: string): number; len(arr: any[]): number; len(x: any) { return x.length; }}
override
#
TypeScript์์๋ ํ์ ํด๋์ค๊ฐ ํญ์ ๊ธฐ๋ณธ ํด๋์ค์ ํ์ ์ ํ์ด ๋๋๋ก ํ๋ค.
class Base { greet() { console.log('Hello, world!'); }}
class Derived extends Base { greet(name?: string) { if (name === undefined) { super.greet(); } else { console.log(`Hello, ${name.toUpperCase()}`); } }}
const d = new Derived();d.greet();d.greet('reader');
ํ์ ํด๋์ค๊ฐ ๊ธฐ๋ณธ ํด๋์ค์ ๊ท์น์ ๋ฐ๋ฅด๋ ๊ฒ์ด ์ค์ํ๋ฐ, ๊ธฐ๋ณธ ํด๋์ค๊ฐ ํ์ ํด๋์ค ์ธ์คํด์ค๋ฅผ ์ฐธ์กฐํ ์ ์์ด์ผ ํ๋ค.
// Alias the derived instance through a base class referenceconst b: Base = d;// No problemb.greet();
๋ง์ฝ ํ์ ํด๋์ค๊ฐ ๊ธฐ๋ณธ ํด๋์ค๋ฅผ ๋ฐ๋ฅด์ง ์๋๋ค๋ฉด ์๋ฌ๊ฐ ๋ฐ์ํ๋ค.
class Base { greet() { console.log('Hello, world!'); }}
class Derived extends Base { // Make this parameter required greet(name: string) { // Property 'greet' in type 'Derived' is not assignable to the same property in base type 'Base'. // Type '(name: string) => void' is not assignable to type '() => void'. console.log(`Hello, ${name.toUpperCase()}`); }}
const b: Base = new Derived();// Crashes because "name" will be undefinedb.greet();
#
์ ๊ทผ ์ ์ด์(Access Modifier)public
: ๊ธฐ๋ณธ์ ์ผ๋ก ๋ชจ๋ ๋ฉค๋ฒ๋public
์ผ๋ก ์ด๋์๋ ์ ๊ทผํ ์ ์๋ค.protected
: ํด๋์ค ์์ ๊ณผ ์์ ํด๋์ค์์๋ง ์ ๊ทผํ ์ ์๋ค.private
:protected
์ ์ ์ฌํ๊ฒ ํด๋์ค ์์ ์์๋ง ์ ๊ทผํ ์ ์์ง๋ง, ์์ ํด๋์ค์์๋ ์ ๊ทผํ ์ ์๋ค.
Why No Static Classes?#
TS(JS)๋ Java๋ C#์์ ์ฌ์ฉํ๋ static class
๋ผ๊ณ ๋ถ๋ฆฌ๋ ๊ตฌ์กฐ๋ฅผ ์ฌ์ฉํ์ง ์๋๋ค. (static class
๋ ์ธ์คํด์คํ ํ ์ ์๋ค.)
๋ฐ๋ผ์, static class
๋ฌธ๋ฒ์ ์ฌ์ฉํ๋ ๊ฒ์ ๋ถํ์ํ๋ค. ๋จ์ง ๋จ์ ๋ฆฌํฐ๋ด ๊ฐ์ฒด๋ฅผ์ฐ๋ ๊ฒ๊ณผ ๋์ผํ๋ค.
// Unnecessary "static" classclass MyStaticClass { static doSomething() {}}
// Preferred (alternative 1)function doSomething() {}
// Preferred (alternative 2)const MyHelperObject = { dosomething() {},};
abstract
#
์์ง ๊ตฌํํ์ง ์์ ๋ฉ์๋์ ํ๋กํผํฐ์ abstract
ํค์๋๋ฅผ ์ฌ์ฉํ ์ ์๋ค. abstract
๋ฉค๋ฒ๋ฅผ ๊ฐ์ง ํด๋์ค๋ ๋ฐ๋์ abstarct class
์ฌ์ผ ํ๋ค.
abstract class
์ ์ญํ ์ abstract
๋ฉค๋ฒ๋ฅผ ๊ตฌํํ ์๋ธ ํด๋์ค์ ๊ธฐ์ด ํด๋์ค๊ฐ๋๋ ๊ฒ์ด๋ค.
abstract class Base { abstract getName(): string;
printName() { console.log('Hello, ' + this.getName()); }}
class Derived extends Base { getName() { return 'world'; }}
const d = new Derived();d.printName();