TypeScript Essentials
Short book about the TypeScript and tsconfig.json
1. TSC Transpiler ๐ฉโ๐ป
JavaScript ๋ Interpreter Language ์ด๋ค. ๊ทธ๋ฆฌ๊ณ ์ด๊ฒ์ ํ์ฅํ TypeScript ๋ ์น ๋ธ๋ผ์ฐ์ ๊ฐ JavaScript ๋ง ์ดํดํ ์ ์๊ธฐ ๋๋ฌธ์ ๋ณํ์ ํด์ผํ๋๋ฐ ์ด ๊ณผ์ ์ Transpile ์ด๋ผ ํ๋ค.
Compile Language ๊ฐ ์๋๊ธฐ ๋๋ฌธ์ Transpile ์ด๋ผ๊ณ ๊ตฌ๋ถ์ง๊ธฐ๋ ํ๊ณ , ๋ค๋ฅธ ์ปดํ์ผ ์ธ์ด์ ๋ง์ฐฌ๊ฐ์ง๋ก
Runtime ์ด์ ์ ์ค๋ฅ๋ฅผ ์ฐพ์๋ผ ์ ์๊ธฐ ๋๋ฌธ์ Compile ์ด๋ผ ๋ถ๋ฅด๋ ๊ฒฝ์ฐ๋ ์กด์ฌํ๋ค. ์๋ฌดํผ ์ด๋ ์ฌ์ฉ๋๋
๊ฒ์ด ๋ฐ๋ก TSC
๋ค.
TypeScript ๋ Global ๋ก ์ค์นํ๊ฑฐ๋ Local ๋ก ์ค์นํ ์ ์๋ค. Global ๋ก ์ค์นํ์๋์ ๋ค๋ฅด๊ฒ Local ๋ก ์ค์นํ์ ๊ฒฝ์ฐ ๊ฒฝ๋ก๋ฅผ ์ง์ ํด์ค์ผํ๋ฉฐ ๋ค์ ๋ ์ค ํ๋๋ฅผ ์ด์ฉํด ์คํํ ์ ์๋ค.
./node_modules/.bin/tsc --init
./node_modules/typescript/bin/tsc --init
๊ทธ ์ธ์๋ npx
๋ฅผ ์ฌ์ฉํ๊ฑฐ๋
npx tsc
package.json
ํ์ผ์ ์ฌ์ฉํดํ ์ ์๋๋ฐ, ์ด๋๋ NPM Project ๋ก ๋ง๋ค์๊ธฐ ๋๋ฌธ์tsc
๋ผ๊ณ ๋ง ์ณ๋
Local ๋ก ์ค์นํ ํจํค์ง ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ธ์ํ ์ ์๋ค.
{
"scripts": {
"build": "tsc"
}
}
2. Basic Types ๐ฉโ๐ป
1. Types
ECMAScript Types
- Boolean
- Number
- String
- Symbol (ECMAScript 6 ์ถ๊ฐ)
- Null
- Undefined
- Array (์ค์ ๋ก๋ Object)
TypeScript Types
- Any, Void, Never, Unknown
- Enum
- Tuple (์ค์ ๋ก๋ Object)
2. Primitive Types
Object ์ Reference ํํ๊ฐ ์๋ ์ค์ ๊ฐ
์ ์ ์ฅํ๋ ์๋ฃํ์ ๋งํ๋ค.
- boolean
- number
- string
- symbol (ES2015)
- null
- undefined
JavaScript ์ ์ฒ๋ฆฌ ๋ฐฉ์์ผ๋ก Primitive Types ์ ๋ด์ฅ ํจ์๋ฅผ ์ฌ์ฉ ๊ฐ๋ฅํ๋ค.
let name = 'Mark' name.toString()
Primitive Types ๋ literal
๊ฐ์ผ๋ก Primitive Types ์ Sub Types ๋ฅผ ๋ํ๋ผ ์ ์๋ค.
true // Primitive Type `boolean`์ `Sub Type`
'hello'
3.14
null
undefined
new
๋ฅผ ์ฌ์ฉํด Wrapper Object ๋ก ๋ง๋ Types ๋ Primitive Types ๊ฐ ์๋๊ณ Object ๋ค.new Boolean(false) // typeof new Boolean(false) : 'object' new String( 'world') // typeof new String('world') : 'object' new Number (42) // typeof new Number (42) : 'object'
Type Casting
๋ค๋ฅธ ์ธ์ด์์ String ๊ณผ ๊ฐ์ ํ์ ์ ๋ํ๋ผ ๋ ๋๋ฌธ์๋ก ํํํ๋ ๊ฒ๊ณผ ๋ฌ๋ฆฌ TypeScript ๋ Object Types ์ ๊ตฌ๋ถํ๊ธฐ ์ํด Primitive Types ๋ฅผ ๋ชจ๋
Lower-case
๋ก ํํํ๋ค.
3. boolean
let isDone: boolean = false;
isDone = true;
console.log(typeof isDone); // 'boolean'
4. number
JavaScript ์ ๋ง์ฐฌ๊ฐ์ง๋ก TypeScript ์ ๋ชจ๋ ์ซ์๋ ๋ถ๋ ์์์ (Floating Point) ๊ฐ์ด๋ค.
let decimal: number = 6; // 10์ง์ ๋ฆฌํฐ๋ด
let hex: number = 0xf00d; // 16์ง์ ๋ฆฌํฐ๋ด
let binary: number = 0b1010; // 2์ง์ ๋ฆฌํฐ๋ด
let octal: number = 0o744; // 8์ง์ ๋ฆฌํฐ๋ด
let notANumber: number = NaN;
let underscoreNum: number = 1_000_000;
5. string
JavaScript ์ ๋ง์ฐฌ๊ฐ์ง๋ก Template String ์ ์ง์ํ๋ค.
let fullName: string = 'Harry Potter';
let age: number = 17;
let sentence: string = `Hello, My name is ${fullName}.
I'll be ${age + 1} years old next month.`;
console.log(sentence);
Hello, My name is Harry Potter.
I'll be 18 years old next month.
6. symbol
- ECMAScript2015 ์ Symbol ๋ก
new Symbol
๋ก ์ฌ์ฉํ ์ ์๋ค. Symbol ์ ํจ์๋ก ์ฌ์ฉํด์symbol
Type ์ ๋ง๋ค์ด ๋ผ ์ ์๋ค. - Primitive Types ์ ๊ฐ์ ๋ด์์ ์ฌ์ฉํ๋ฉฐ,
Unique
ํ๊ณ ,Immutable
ํ ๊ฐ์ ๋ง๋ค์ด ์ฃผ๋ก ์ ๊ทผ์ ์ ์ดํ๋๋ฐ ์ฌ์ฉ๋๋ค.
console.log(Symbol('foo') === Symbol('foo')); // false
const sym = Symbol();
const obj = {
[sym]: 'value',
};
// console.log(obj['sym']); // TypeError
console.log(obj[sym]);
7. null & undefined
tsconfig
์ค์ ์ ํ์ง ์์ผ๋ฉด null
๊ณผ undefined
๋ ๋ค๋ฅธ ๋ชจ๋ ํ์
์ subtypes
๋ก ์กด์ฌํ๋ค.
let name: string = null;
let age: number = undefined;
์ปดํ์ผ ์ต์
์์ --stringNullChecks
๋ฅผ ์ฌ์ฉํ๋ฉด null
์ ์๊ธฐ ์์ ์๊ฒ๋ง, undefined
๋ ์๊ธฐ ์์ ๊ณผ
void
์๊ฒ๋ง ํ ๋นํ ์ ์๋ค. ๋ง์ฝ ๋ค๋ฅธ ํ์
์ด ํ ๋นํ ์ ์๊ฒ ํ๋ ค๋ฉด Union Types
๋ฅผ ์ฌ์ฉํด์ผํ๋ค.
let n: null = null;
let v1: void = null; // TypeError
let u: undefined = undefined
let v2: void = undefined;
null
null
์ด๋ผ๋ ๊ฐ์ผ๋ก ํ ๋น๋ ๊ฒ์null
์ด๋ผ๊ณ ํ๋ค.- ๋ฌด์ธ๊ฐ๊ฐ ์๋๋ฐ, ์ฌ์ฉํ ์ค๋น๊ฐ ๋ ๋ ์ํ.
null
type ์null
์ด๋ผ๋ ๊ฐ๋ง ๊ฐ์ง ์ ์๋ค.- Runtime ์์
typeof
์ฐ์ฐ์๋ฅผ ์ด์ฉํด ์์๋ด๋ฉด,object
๋ฅผ ๋ฐํํ๋ค.
let n: null = null;
console.log(n); // null
console.log(typeof n); // object
undefined
- ๊ฐ์ ํ ๋นํ์ง ์์ ๋ณ์๋
undefined
๋ผ๋ ๊ฐ์ ๊ฐ๋๋ค. - ๋ฌด์ธ๊ฐ๊ฐ ์์ ์ค๋น๊ฐ ์ ๋ ์ํ.
Object
์ Properties ๊ฐ ์์ ๋๋undefined
๋ฅผ ๊ฐ๋๋ค.- Runtime ์์
typeof
์ฐ์ฐ์๋ฅผ ์ด์ฉํด ์์๋ด๋ฉด,undefined
๋ฅผ ๋ฐํํ๋ค.
let u: undefined = undefined;
console.log(u); // undefined
console.log(typeof u); // undefined
8. object
TypeScript ์ object
๋ ์ฐ๋ฆฌ๊ฐ ๊ฐ์ฒด๋ผ ๋ถ๋ฅด๋ ๊ฒ๊ณผ๋ ์กฐ๊ธ ๋ค๋ฅด๊ฒ ์ฌ์ฉ๋๋ค. TypeScript ์์ object
๋
Primitive Types ๊ฐ ์๋ ๊ฒ์ ๋ํ๋ด๊ณ ์ถ์ ๋ ์ฌ์ฉํ๋ ํ์
์ด๋ค.
Non-Primitive Types
number, string, boolean, bigint, symbol, null, undefined ๊ฐ ์๋ ๊ฒ
// created by object literal
const person1 = {
name: 'Mark',
age: 25,
};
// created by Object.create
const person2 = Object.create({
name: 'Mark',
age: 25,
});
์ฆ,
Object.create
๋ Parameters ๋กobject
๋๋null
์ ๋ฐ์ ์ ์๋ค. ๋ํ JavaScript ์์ Array ๋ Object ์ ์ผ์ข ์ด๊ธฐ ๋๋ฌธ์ Array ์ญ์ ๋ฃ์ ์ ์๋ค.
9. Array
- ๊ฐ์ ํ์ ์ elements ๋ฅผ ๋ชจ์ ๋์ ์๋ฃํ์ ์๋ฏธํ๋ค.
- ๋ค๋ฅธ ์ธ์ด์ ๋ฌ๋ฆฌ
any
ํ์ ์ ์ฌ์ฉํ์ง ์๊ณ ๋union
ํ์ ์ ์ฌ์ฉํด ์๋ก ๋ค๋ฅธ ํ์ ์ elements ๋ฅผ ๋ชจ์ ๋ฐฐ์ด์ ๋ง๋ค ์ ์๋ค.
let list1: number[] = [1, 2, 3, 4, 5];
let list2: Array<number> = [1, 2, 3, 4, 5];
let list3: (number | string)[] = [1, '2', 3, '4', 5];
let list4: Array<number | string> = [1, '2', 3, '4', 5];
10. Tuple
JavaScript ์ tuple
์ด ์กด์ฌํ์ง ์๊ธฐ ๋๋ฌธ์ Array ๋ฅผ ์ฌ์ฉํด ๊ตฌํํ๋ค.
let person1: [string, number] = ['Mark', 25];
let person2: Array<string | number> = ['Mark', 25];
const [name, age] = ['Mark', 25];
11. any
- ํ์
์ด ์ ํด์ง์ง ์์ ๋ถ๊ฐ๋ฅํ๋ค๋ ๊ฒ์ด ์๋ ์ด๋ค ํ์
์ด์ด๋ ์๊ด ์๋ ํ์
์ผ๋ก
any.toString()
๊ฐ์ ๊ฒ์ ํด๋ ์๋ฌ๋ก ์ธ์ํ์ง ์๋๋ค. - ๋ฐ๋ผ์ Compiler ๊ฐ ์๋ฌ๋ฅผ ์ฌ์ ์ ํ์ธํ ์ ์๊ธฐ ๋๋ฌธ์ ์ต๋ํ ์ฌ์ฉํ์ง ์์์ผ ํ๋ค.
noImplicitAny
์ต์ ์any
๋ฅผ ์๋์ ์ผ๋ก ํํํ๊ฑฐ๋ ๋ช ํํ ํ์ ์ ์ง์ ํ๋๋ก ๊ฐ์ ํด ๊ฐ๋ฐ์๊ฐ ์์ ํ ์ฝ๋๋ฅผ ์์ฑํ๋๋ก ํ๋ค.
function returnAny(message: any) {
console.log(message);
}
์์ ๊ฐ์ ๊ฒฝ์ฐ ๋ณ๋ค๋ฅธ ์ํธ์์ฉ์ ํ๊ฑฐ๋ ์๋ฌ๋ฅผ ๋ฐ์์ํค์ง ์์ผ๋ฏ๋ก ๊ฐ๋ฐ์๊ฐ ๋ช
์์ ์ผ๋ก any
๋ฅผ ์ฌ์ฉํ ์ ์๋ค.
์ฆ, any
๋ฅผ ์ฌ์ฉํ๋ค๋ ๊ฒ์ ์ด๊ฒ์ด ์๋ฌ๋ฅผ ๋ฐ์์ํค์ง ์์์ ๋ํ ์ฑ
์์ด ๊ฐ๋ฐ์์๊ฒ ์ฃผ์ด์ง๋ค.
์ด๋ค ํ์
์ด ๋ค์ด์ฌ์ง ๋ชจ๋ฅด๊ฑฐ๋ ๊ท์ฐฎ์ any
๋ฅผ ์ฌ์ฉํ๋ ค ํ๋ค๋ฉด ๋ฐ๋์ union
ํ์
์ ์ฌ์ฉํ๋๋ก ๊ณ ์ณ์ผ ํ๋ค.
any ๋ object ๋ฅผ ํตํด ๊ณ์ํด์ ์ ํ๋๊ธฐ ๋๋ฌธ์ด๋ค.
let anyType: any = {};
let alsoAny = anyType.a.b.c.d.e;
์ด๊ฒ์ Optional Chaining ๊ณผ ์ ์ฌํ๋ค๋ ๊ฒ์ ์ ์ ์๋ค. ๊ฐ์ฒด์ ์ด๋ค property ์ ์ ๊ทผํ๊ธฐ ์ํด ๋จ ํ ๋ฒ์ด๋ผ๋ Optional Chaining ์ ํ๊ฒ ๋๋ฉด, ๊ฒฐ๊ณผ๋ ํญ์ Optional ์ธ ๊ฒ์ฒ๋ผ, Object ์ ๋จ ํ ๋ฒ์ด๋ผ๋ any ๋ฅผ ์ฌ์ฉํ๋ฉด, ๊ฒฐ๊ณผ๋ ํญ์ any ๊ฐ ๋๋ค.
์์ ๊ฐ์ any
์ ํ๋ก ์ธํ ๋์๋ฅผ ๋ง๊ธฐ ์ํด ๋ค์๊ณผ ๊ฐ์ด ์ค๊ฐ์ ํ์
์ ์ง์ ํ ์ ์๋ค.
function leakingAny(obj: any) {
const a = obj.num;
const b = a + 1;
return b;
}
const something = leakingAny({ num: 10 });
something.indexOf('0');
something ์ด any
ํ์
์ด๊ธฐ ๋๋ฌธ์ ์๋ฌ๊ฐ ๋ฐ์ํ์ง ์๋๋ค.
function leakingAny(obj: any) {
const a: number = obj.num;
const b = a + 1;
return b;
}
const something = leakingAny({ num: 10 });
something.indexOf('0'); // error, Property 'indexOf' does not exist on type 'number'
a ๋ฅผ number
๋ก ํ์
์ ์ง์ ํ๋ ์๊ฐ b ์ something ์ญ์ number
ํ์
์ผ๋ก ์ง์ ๋๋ค. ๋ฐ๋ผ์ number
๋
indexOf
๋ฅผ ๊ฐ์ง๊ณ ์์ง ์๊ธฐ ๋๋ฌธ์ ์ปดํ์ผ๋ฌ๋ ์๋ฌ๋ฅผ ๊ฐ์งํ๋ค. ์ฆ, any
๋์๋ฅผ ๋ง์ ๊ฒ์ด๋ค. ํ์ง๋ง ์ด์ ๊ฐ์
๋ฐฉ์์ผ๋ก any
๋์๋ฅผ ๋ง๋ ๊ฒ์ ์ข์ ๋ฐฉ๋ฒ์ด ์๋๋ค. Type Guard ๋ฅผ ์ฌ์ฉํด unknown
์ ์ฌ์ฉํ๋ ๊ฒ์ด ์ข์ ๋ฐฉ๋ฒ์ด๋ค.
12. unknown
์ฑ์ ๋ง๋ค๋ค ๋ณด๋ฉด ๋์ ์ฝํ
์ธ ์ ๊ฐ์ด ์๋์ ์ผ๋ก ๋ชจ๋ ๊ฐ์ ์๋ฝํ๊ธฐ๋ฅผ ์ํ๊ฑฐ๋ ์์ฑํ ๋ ๋ชจ๋ฅด๋ ๋ณ์์ ํ์
์ ๋ฌ์ฌํด์ผ ํ ์๋
์๋ค. ์ด ๊ฒฝ์ฐ any
๋ฅผ ์ฌ์ฉํด Any Leaking ์ํ์ ๊ฐ์ํ๋ ๋์ Compiler ์ ๋ค๋ฅธ ์ฌ๋์๊ฒ ์ด๋ฅผ
์๋์ ์ผ๋ก ์ด ๋ณ์๊ฐ ๋ฌด์์ด๋ ๋ ์ ์์์ ์๋ ค์ฃผ๋ ํ์
์ผ๋ก unknown
ํ์
์ ์ ๊ณตํ๋ค.
unknown
ํ์
์ any
์ ๋น์ทํ์ง๋ง Type-Safe
ํ ์ฝ๋๋ฅผ ์์ฑํ ์ ์๋๋ก Compiler ๊ฐ ์ด๋ฅผ ์ฝ๋๋ฅผ ๊ฐ์ํ ์ ์๋ค.
unknown
ํ์
์ ์ฌ์ฉํ๋ ค๋ฉด Type Guard ๋ฅผ ์ฌ์ฉํด
declare const maybe: unknown;
if (typeof maybe === 'number') {
const aNumber: number = maybe;
}
TypeScript ์ unknown
ํ์
๊ณผ Type Guard ๋ Swift ์
Any ํ์
๊ณผ Upcating Operator โasโ ์ ์ ์ฌํ๋ค.
var things: [Any] = []
func testAnyTypes(_ things: [Any]) {
for thing in things {
switch thing {
case 0 as Int:
print("\(thing) : zero as an Int")
case 0 as Double:
print("\(thing) : zero as a Double")
case let someInt as Int:
print("\(thing) : an integer value of \(someInt)")
case let someDouble as Double where someDouble > 0:
print("\(thing) : a positive double value of \(someDouble)")
case is Double:
print("some other double value that I don't want to print")
case let someString as String:
print("\(thing) : a string value of \"\(someString)\"")
case let (x, y) as (Double, Double):
print("\(thing) : an (x, y) point at \(x), \(y)")
case let stringConverter as (String) -> String:
print("\(thing) : \(stringConverter("Michael"))")
case let movie as Movie:
print("\(thing) : a movie called \(movie.name), dir. \(movie.director)")
case let point as Point:
print("\(thing) : a point is at (\(point.x), \(point.y))")
case let direction as CompassPoint:
print("\(thing) : a direction is \(direction)")
default:
print("\(thing) : something else")
}
}
}
13. never
๋ณดํต return
์ ์ฌ์ฉ๋๋ค.
- null, undefined์ ๋ง์ฐฌ๊ฐ์ง๋ก ๋ค๋ฅธ ๋ชจ๋ ํ์
์
subtypes
๋ก ์กด์ฌํ๋ค. never
๋ ์ฃผ๋กreturn
์ ์ฌ์ฉ๋๋ฉฐ, ๋ชจ๋ ํ์ ์ ํ ๋นํ ์ ์๋ค. ํ์ง๋งnever
์๋any
๋ฅผ ํฌํจํด ๊ทธ ์ด๋ ๊ฒ๋ ํ ๋นํ ์ ์๋ค.never
์ ์ด๋ฐ ํน์ฑ์ ์ด์ฉํด Type Guard ๋๋ Conditional Types ์ ์ฌ์ฉํ ์ ์๋ค.
never
๋ ๊ฐ์ด ์๋ ํ์
์ผ๋ก๋ง ์ฌ์ฉ๋ ์ ์๋ค
function error(message: string): never {
throw new Error(message);
}
function fail(message: string) {
return error(message);
}
Type Guard ์ ์ฌ์ฉ๋๊ธฐ๋ ํ๋ค
declare const a: string;
if (typeof a !== 'string') {
a; // never
}
declare const b: string | number;
if (typeof b !=='string') {
b; // number
}
Conditional Types ์ ์ฌ์ฉ๋๊ธฐ๋ ํ๋ค
type MessageOf<T extends { message: unknown }> = T['message'];
interface Email {
message: string;
}
type EmailMessageContent = MessageOf<Email>;
// type EmailMessageContent = string
์ ์ฝ๋์์ MessageOf
๊ฐ ์๋ฌด ํ์
์ด๋ ๋ฐ์ ์ ์๋๋ก ํ๋ ค๋ฉด never
ํ์
์ ์ฌ์ฉํด ๋ค์๊ณผ ๊ฐ์ด
Conditional Types
๋ก ๋ฐ๊ฟ ์ ์๋ค.
- Destructuring
type MessageOf<T> = T extends { message: unknown } ? T['message'] : never;
interface Email {
message: string;
}
type EmailMessageContent = MessageOf<Email>;
// type EmailMessageContent = string
interface Dog {
bark(): void;
}
type DogMessageContent = MessageOf<Dog>;
// type DogMessageContent = never
- Flatten
type Flatten<T> = T extends any[] ? T[number] : T;
// type Flatten<T> = T extends Array<infer Item> ? Item : T;
type Str = Flatten<string[]>;
// type Str = string;
type Num = Flatten<number[]>;
// type Num = number;
type Something = Flatten<object>;
// type Something = object;
type K = Flatten<[string, number]>;
// type K = string | number;
- To Array
type ToArray<Type> = Type extends any ? Type[] : never;
type StrArr = ToArray<string>;
// type StrArr = string[];
type StrArrOrNumArr = ToArray<string | number>;
// type StrArrOrNumArr = string[] | number[];
- To Array Non-distributed
type ToArrayNonDist<Type> = [Type] extends [any] ? Type[] : never;
type StrArr = ToArrayNonDist<string>;
// type StrArr = string[];
type ArrOfStrOrNum = ToArrayNonDist<string | number>;
// type ArrOfStrOrNum = (string | number)[];
14. void
๊ฐ์ ๋ฐํํ์ง ์๋ ํจ์์ Return Type
์ผ๋ก ์ฌ์ฉํ๋ค. ๋ค๋ฅธ ์ธ์ด์ ๋ฌธ๋ฒ์ ์ธ ํต์ผ์ฑ์ ์ํด ์ถ๊ฐ๋ ํ์
์ผ๋ก JavaScript ์
์ด๋ฏธ ์กด์ฌํ๋ undefined
๋ผ๋ ํ์
๊ณผ ๋์ผํ๋ค. ํจ์์ Return Type ์ผ๋ก ์ฌ์ฉ๋๋ undefined ์ ๋๋ก ๋ณด๋ฉด ๋๋ค.
function returnVoid(message: string) {
console.log(message);
}
// function returnVoid(message: string): void
const r = returnVoid('no return');
console.log(r); // undefined
void
๋ ์ฌ์คundefined
์ ๊ฐ๋ค. ํ์ง๋ง ๋ช ์์ ์ผ๋กundefined
์ ํ ๋นํ๋ ๊ฒ์ ๋ถ๊ฐ๋ฅํ๋ค.const r: undefined = returnVoid('no return'); // error, Type 'void' is not assignable to type 'undefined'
์ด๋ก์จ TypeScript ์
void
์ญ์ ๋ค๋ฅธ ์ธ์ด์void
์ ์ ์ฌํ๊ฒ ์๋ํ๋ค.
3. Type System ๐ฉโ๐ป
1. Make TypeScript more Strictly
TypeScript ๋ ์ง์ ์คํํ ์ ์๋ ์ธ์ด๊ฐ ์๋๊ณ ์ต์ข ์ ์ผ๋ก JavaScript ๋ก ๋ณํ๋์ด์ผ ํ๋ ์ธ์ด์ด๊ธฐ ๋๋ฌธ์ ๊ฐ๋ ๋ช ๊ฐ์ง ํ๊ณ๊ฐ ์๋ค. ์ด๋ค ํ๊ณ๊ฐ ์๋์ง, ๊ทธ๋ฆฌ๊ณ ์ด๋ป๊ฒ ํ๋ฉด ์ด ๋ฌธ์ ๋ฅผ compile-error ๋ฅผ ๋ฐ์์์ผ ๋ฏธ๋ฆฌ ์๋ฐฉํ ์ ์๋์ง ์์๋ณด์.
noImplicitAny
function foo(a) {
return a * 10
}
noImplicitAny
์ต์
์ ์์ ๊ฐ์ด ์
๋ ฅ๊ฐ์ any
๋ก ๋ฐ์ ์ ์๋ ์ํฉ์ ๋ํด compile-error ๋ฅผ ๋ฐ์์์ผ
๋ช
์์ ์ผ๋ก ํ์
์ ์ง์ ํ๋๋ก ๊ฐ์ ํ๋ค.
strictNullChecks & noImplicitReturns
function foo(a: number) {
if (a > 0) {
return a * 10
}
}
์ด ๊ฒฝ์ฐ a ์ ํ์
์ด ์ง์ ๋๋ฉฐ Return Type ์ด number ๋ก ์ถ๋ก ๋๋ค. ํ์ง๋ง a ๊ฐ ์์๊ฐ ์๋ ๊ฒฝ์ฐ void
๋ฅผ
๋ฐํํ๊ฒ๋๋ค. ์ฆ, foo(-5) + 10
์ ํ๊ฒ ๋๋ฉด undefined + 5
๊ฐ ๋๋ฏ๋ก NaN
์ด ๋๋ค.
์ด๋ก์จ TypeScript ์ number
๋ ๊ธฐ๋ณธ์ ์ผ๋ก undefined
๋ฅผ ํฌํจํ๊ณ ์์์ ์ ์ ์๋ค.
strictNullChecks
์ต์
์ ๋ชจ๋ ํ์
์ ์๋์ผ๋ก ํฌํจ๋์ด์๋ null
๊ณผ undefined
๋ฅผ ์ ๊ฑฐํ๋ค. ๋ํ
noImplicitReturns
์ต์
์ ์์ ๊ฐ์ ๋ฆฌํด๊ฐ ๋ฌธ์ ๊ฐ ๋ฐ์๋์ง ์๋๋ก Return Type ์ด ์กด์ฌํ๋ ๊ฒฝ์ฐ ๋ช
์์ ์ผ๋ก ํ์
์
์ง์ ํ๋๋ก ๊ฐ์ ํ๋ค.
function foo(a: number): number {
if (a > 0) {
return a * 10;
} else {
throw new Error("Input must be a positive number");
}
}
2. Structural Type System & Nominal Type System
- Structural Type System: ๊ตฌ์กฐ๊ฐ ๊ฐ์ผ๋ฉด ๊ฐ์ ํ์ .
- Nominal Type System: ๊ตฌ์กฐ๊ฐ ๊ฐ์๋ ์ด๋ฆ์ด ๋ค๋ฅด๋ฉด ๋ค๋ฅธ ํ์ .
Structural Type System
interface IPerson {
name: string;
age: number;
speak(): string;
}
type PersonType = {
name: string;
age: number;
speak(): string;
}
let personInterface: IPerson = {} as any;
let personType: PersonType = {} as any;
์ ๋ ํ์ ์ ๋ฌธ๋ฒ์ ์ฐจ์ด๋ ์์ง๋ง ๋ฐ์ดํฐ๋ฅผ ํ ๋นํ ๋ ๋์ผํ ํ์ ์ผ๋ก ๊ฐ์ฃผ๋๋ค(ํ์ ์ ํ์ฅํ๊ฑฐ๋ ํ ๋ ๋ฌธ๋ฒ์ ์ฐจ์ด๋ ์กด์ฌํ๋ค).
Nominal Type System
C
์ ๊ฐ์ ์ธ์ด๋ ๊ตฌ์กฐ๊ฐ ๊ฐ์๋ ์ด๋ฆ์ด ๋ค๋ฅด๋ฉด ๋ค๋ฅธ ํ์
์ด๋ค. ์ฆ, TypeScript ๋ ์ด๋ฌํ ํ์
์์คํ
์ ๋ฐ๋ฅด์ง ์๋๋ค.
๋ง์ฝ, ์ด๋ฌํ ํ์
์ด ํ์ํ ๊ฒฝ์ฐ ๋ค์๊ณผ ๊ฐ์ด symbol
์ ์ด์ฉํด ์ ์ฌํ ๊ตฌํ์ ๊ฐ๋ฅํ๋ค.
type PersonId = string & { readonly brand: unique symbol }
function PersonId(id: string): PersonId {
// id ๊ฒ์ฆ ๋ก์ง...
return id as PersonId;
}
function getPersonById(id: PersonId) { }
getPersonById(PersonId('id-327364'));
getPersonById('id-327364'); // error TS2345
์์ ๊ฐ์ ๋ฐฉ๋ฒ์ผ๋ก ๊ฐ์ ํํ์ง๋ง ๋ค๋ฅธ ๊ณ ์ ํ ํ์ ์ผ๋ก ๋ง๋ค ์ ์๋ค.
3. Type Compatibility
// sub1 ํ์
์ sup1 ํ์
์ `Sub-Type`์ด๋ค.
let sub1: 1 = 1;
let sup1: number = sub1;
sub1 = sup1; // error
// sub2 ํ์
์ sup2 ํ์
์ `Sub-Type`์ด๋ค.
let sub2: number[] = [1];
let sup2: object = sub2;
sup2 = sup2; // error
// sub3 ํ์
์ sup3 ํ์
์ `Sub-Type`์ด๋ค.
let sub3: [number, number] = [1, 2];
let sup3: number[] = sub3;
sub3 = sup3; // error
TypeScript ์ ํ์
ํธํ์ฑ์ ์์ ๊ฐ์ด ๋ค๋ฅธ ์ธ์ด๋ค๊ณผ ํฌ๊ฒ ๋ค๋ฅด์ง ์๋ค. ํ์ง๋ง function
์ ํ์
์ ๋ํด์ ํ์ ํธํ ๋ฟ
์๋๋ผ ์์ ํธํ๊น์ง ๋๋ค, ์ต์ข
Runtime Code ์ธ JavaScript ์์ ์ด๋ฐ ๊ฒ์ด ๊ฐ๋ฅํ๊ธฐ ๋๋ฌธ์ด๋ค.
class Person {}
class Developer extends Person { }
class JuniorDeveloper extends Developer { }
function tellMe(f: (d: Developer) => Developer) {}
// Parameter ์ Developer => Developer ๋ฅผ ์ ๋ฌ.
tellMe((d: Developer): Developer => new Developer()) // OK
// Parameter ์ Person => Developer ๋ฅผ ์ ๋ฌ.
tellMe((p: Person): Developer => new Developer()) // Super-Type ์ ์ํ Sub-Type ํ์ ํธํ
// Parameter ์ JuniorDeveloper => Developer ๋ฅผ ์ ๋ฌ.
tellMe((j: JuniorDeveloper): Developer => new Developer()) // Sub-Type ์ด Super-Type ์ ์์ ํธํ
tellMe
์ 3๋ฒ์งธ ํธ์ถ์ ๋ค๋ฅธ ์ธ์ด์์ ๋ณด๋ฉด ๋ถ๋ช
์๋ชป๋ ํธ์ถ์ด๋ค. ํ์ง๋ง TypeScript ์์๋ ์ด๊ฒ์ด ๊ฐ๋ฅํ๋ฉฐ,
์ฌ์ง์ด ์๋ฌ๊ฐ ์๋๋ค. Make TypeScript more Strictly ์์ ๋ณธ ๊ฒ์ฒ๋ผ
์ด๊ฒ ์ญ์ compile-error ๋ฅผ ๋ฐ์์ํฌ ์ ์๋๋ฐ, strictFunctionTypes
์ต์
์ ํ์ฑํ ํ๋ฉด ๋๋ค.
๋ฐ๋ผ์ TypeScript ์์
noImplicitAny
,strictNullChecks
,noImplicitReturns
,strictFunctionTypes
์ด 4๊ฐ์ ์ต์ ์ ์์ ํ ์ฝ๋ ์์ฑ์ ์ํด ํ์ฑํ ํด์ฃผ๋๋ก ํ๋ค. ์ด ์ต์ ๋ค์ TypeScript ๋ฅผ ํ์ ์ ๋ํด ์๊ฒฉํ ๋ค๋ฅธ ์ธ์ด๋ค๊ณผ ์ ์ฌํ ํ๊ฒฝ์ ๋ง๋ค์ด์ค๋ค.
4. Type Alias
interface
์ ๋น์ทํ์ง๋ง ๋ค๋ฅธ ์ธ์ด์ ๋ง์ฐฌ๊ฐ์ง๋ก ๋ง๋ค์ด์ง ํ์
์ refer
๋ก ์ฌ์ฉํ๋ ๊ฒ์ด์ง ์ง์ ํ์
์ ๋ง๋๋ ๊ฒ์ ์๋๋ค.
interface
๋ฅผ Type Alias
๋ก ๋์ฒดํ๋ ๊ฒ์ด ๊ฐ๋ฅํ ์ด์ ๋ TypeScript ๊ฐ Object Literal
๊ทธ ์์ฒด๋ฅผ ํ์
์ผ๋ก
์ ์ํ ์ ์๊ธฐ ๋๋ฌธ์ด๋ค.
interface
๋ ๋จ์ง Object ํํ๋ง ์ ์๊ฐ ๊ฐ๋ฅํ์ง๋ง, type
์ ๋ ์ ์ฐํ๊ฒ ์ฌ์ฉํ ์ ์๋ค. ์ฃผ๋ก ๋ฐ๋ณต๋๋ ํ์
์ด๋
Union Types ๋ฅผ ์ ์ํ ๋ ์ฌ์ฉํ๋ค.
๋ช ํํ ์ด์ผ๊ธฐํ๋ฉด
interface
์type
์ ๋ฌธ๋ฒ์ ์ผ๋ก๋ ๊ธฐ๋ฅ์ ์ผ๋ก๋ ๋ค๋ฅด๋ค. ํ์ง๋ง ๋๋ถ๋ถ์ ๊ฒฝ์ฐ Object ํํ์ ํ์ ์ ์ ์ํ ๋interface
๋ฅผ ์ฌ์ฉํ๋ ๊ฒ๊ณผtype
์ ์ฌ์ฉํ๋ ๊ฒ ๋ชจ๋ ๊ฐ๋ฅํ๊ธฐ ๋๋ฌธ์ ์ค์ ๋ก ์ด ๋ถ๋ถ์ ์์ด์ ์ด๋ค ๊ฒ์ ์ฌ์ฉํ๋ ๊ฒ์ด ๋ ์ ์ ํ๊ฐ์ ๋ํ ์๊ฒฌ์ด ๋ค์ํ๋ค.์ด์ฐจํผ Structural Type System ์ด๊ธฐ ๋๋ฌธ์ ๋ฐ๋์
interface
๋ฅผ ์จ์ผ ํ๊ฑฐ๋,type
์ ์จ์ผํ๋ ๊ฒฝ์ฐ๊ฐ ์๋๋ผ๋ฉด ํด๋น ์ฑ์ ๋ํ ์ฝ๋ฉ ์ปจ๋ฒค์ ์ ์ ์ํ๊ณ ์ด์ ๋ฐ๋ฅด๋๋ก ํ๋ฉด ๋๋ค.
4. TypeScript Compiler ๐ฉโ๐ป
1. Compilation Context
TypeScript ์ฝ๋๋ฅผ ์ด๋ป๊ฒ JavaScript ์ฝ๋๋ก ๋ณํํ ๊ฑด์ง๋ฅผ ์ ์ํ๋ ๋ฐฉ๋ฒ์ผ๋ก tsconfig.json
์ ์ฌ์ฉํ๋
๊ฒ์ด ๊ถ์ฅ๋๋ฉฐ, tsconfig ์ ์ต์์ ํ๋กํผํฐ๋ ํฌ๊ฒ 3๊ฐ์ง๋ ๋ค์๊ณผ ๊ฐ๋ค.
compilerOptions
: TypeScript ๋ฅผ JavaScript ๋ก ๋ณํํ๊ธฐ ์ํด ํ์ํ ์ธ๋ถ ์ค์ ์ ์ ์include
: JavaScript ๋ก Transpile ํ ํ์ผ์ ๊ฒฝ๋ก ๋ชฉ๋ก์ ๋ฐฐ์ด๋ก ์์ฑexclude
: Transpile ์์ ์ ์ธํ ํ์ผ์ ๊ฒฝ๋ก ๋ชฉ๋ก์ ๋ฐฐ์ด๋ก ์์ฑ
{
"compilerOptions": {
"lib": [
"ESNext",
"DOM"
],
"module": "ESNext",
"moduleResolution": "Node",
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"strict": true,
"skipLibCheck": true
},
"include": ["src/**/*.ts"],
"exclude": ["node_modules"]
}
๋ฌผ๋ก ์ด 3๊ฐ ์ธ์๋ ๋ ๋ง์ ์ต์์ ํ๋กํผํฐ๊ฐ ์กด์ฌํ๋ ๋ฐ ์ 3๊ฐ๊ฐ ๊ฐ์ฅ ํต์ฌ์ด๋ผ๊ณ ํ ์ ์๋ค.
2. tsconfig schema
์์์ ์๊ฐํ compilerOptions
, include
, exclude
์ธ์๋ TypeScript ์ ๋ฒ์ ์ด ์ฌ๋ผ๊ฐ๋ฉฐ ์๋ก์ด ๊ธฐ๋ฅ์ด
์๊ธฐ๊ฑฐ๋ ์ธ๋ถํ ๋๋ฉฐ ์ด ์คํค๋ง์ ํฌ๊ธฐ ์ญ์ ์ฆ๊ฐํ๊ณ ์๋ค. ๊ทธ ์ค ์ค์ํ ์ต์์ ํ๋กํผํฐ๋ฅผ ์ข ๋ ์์ธํ ์์๋ณด์.
- compilerOptions
- compileOnSave
- extends
- files / include / exclude
- references
npx tsc --init
์ ๋ง์ด ์ฌ์ฉ๋๋ ์ผ๋ถ๋ง ์์ฑํด์ฃผ๋ ๊ฒ์ด์ง ๋ชจ๋ ๊ฒ์ ์์ฑํด์ฃผ์ง๋ ์๋๋ค. ๋ชจ๋ ์ต์
๊ณผ ์ค๋ช
์ ๋ณด๋ ค๋ฉด
TSConfig Reference ๋ฅผ ํตํด ํ์ธํ๋๋ก ํ๋ค. ๊ทธ๋ฆฌ๊ณ ๋ ํผ๋ฐ์ค ํ์ด์ง์ ๋ถ์กฑํ ๋ณด์ด ์ค๋ช
์ TypeScript - tsconfig
์ ์ ์ ๋ฆฌ๋์ด ์์ผ๋ ํจ๊ป ์ฐธ๊ณ ํ๋ค.
1. compileOnSave
{
"compileOnSave": true
}
์ด ์ต์
์ TypeScript ์์ฒด Config ์ต์
์ด ์๋๋ค. VS Code ์ Atom TypeScript
ํ๋ฌ๊ทธ์ธ์ ์ค์นํด์ผ
์ฌ์ฉํ ์ ์๋ ์ต์
์ผ๋ก Compile on save ๋ฅผ ์ฐธ๊ณ ํ๋ค. ์๋์ผ๋ก ์ปดํ์ผ๊ณผ ์ ์ฅ์ ์ํํด ๋ฌธ๋ฒ์ ์๋ฌ๋ฅผ ๋ฐ๊ฒฌํ๊ธฐ ์ฝ๋๋ก
ํด์ค๋ค.
๋ง์ฝ JetBrains ๊ณ์ด์ IDE ๋ฅผ ์ฌ์ฉํ ๊ฒฝ์ฐ ์ ํ๋กํผํฐ ์ค์ ์์ด IDE ๊ฐ ๊ธฐ๋ณธ์ผ๋ก ์ง์ํ๋ค.
2. extends
TypeScript ์์ฒด Config ์ต์ ์ด์ง๋ง ๊ธฐ๋ณธ๊ฐ์ ์๋๋ผ ํ์ํ ๊ฒฝ์ฐ ์์ฑํด์ ์ฌ์ฉํด์ผํ๋ค. ์ด๊ฒ์ JSON ํ์ผ์ ์ฌ๋ฌ ๊ฐ๋ก ๋๋์ด ํ์ฅ์ ํตํด ๊ด๋ฆฌํ ์ ์๋๋ก ํด์ฃผ๋ ์ต์ ์ด๋ค.
- base.json
{
"compilerOptions": {
"strict": true,
"noImplicitAny": true,
"strictNullChecks": true,
"strictFunctionTypes": true
}
}
- tsconfig.json
{
"extends": "./base",
"compilerOptions": {
// ...
}
}
์ด๋ ๊ฒ ์ฌ์ฉํ๋ฉด tsconfig.json
์ base.json
์ ๋ด์ฉ์ ํ์ฅ์ ํตํด ๊ฐ๊ฒ ๋๋ค. tsconfig / bases ์ ๊ฐ๋ฉด
์ฌ๋ฌ ๊ฐ๋ฐ ํ๊ฒฝ๋ณ๋ก ๋ง์ถ ๊ธฐ๋ณธ์ผ๋ก ์ฌ์ฉํ๋ฉด ์ข์ tsconfig
์ค์ ์ ์ ๊ณตํ๋ค. ๋ค์์ CRA ์ ์ฌ์ฉํ ๊ฒฝ์ฐ์ ์์๋ค.
npm install --save-dev @tsconfig/create-react-app
yarn add --dev @tsconfig/create-react-app
{
"extends": "@tsconfig/bun/tsconfig.json"
}
3. files, include, exclude
files
{
"files": [
"core.ts",
"sys.ts",
"types.ts",
"scanner.ts",
"parser.ts",
"utilities.ts",
"binder.ts",
"checker.ts",
"emitter.ts",
"program.ts",
"commandLineParser.ts",
"tsc.ts",
"diagnosticInformationMap.generated.ts"
]
}
์ ๊ฐ์ด ๋ฆฌ์คํธ ๋ฐฐ์ด๋ก ์์ฑํ๋ค. ์๋ ๊ฒฝ๋ก์ ์ ๋ ๊ฒฝ๋ก๋ฅผ ๋ชจ๋ ์ง์ํ๋ฉฐ ๊ฐ๋ณ ํ์ผ ๋ชฉ๋ก์ ์ ๋ถ ์ ๋ ฅํด์ค์ผํ๋ค. ์ด๊ฒ์ ํ์ผ์ ๊ฐ์๊ฐ ์ ๊ณ , ์ปดํ์ผ ํ๊ณ ์ ํ๋ ํ์ผ์ ์ง์ ํด์ผํ ๋ ์ ์ฉํ๋ค.
include & exclude
{
"include": [
"src/**/*.ts"
],
"exclude": [
"node_modules",
"**/*.spec.ts"
]
}
๊ผญ ํจ๊ป ์ฌ์ฉํ ํ์๋ ์์ผ๋ ์ผ๋ฐ์ ์ผ๋ก ์์ ๊ฐ์ ํํ๋ก ํจ๊ป ์ฌ์ฉํ๋ค. .gitignore
ํ์ผ์ฒ๋ผ glob
ํจํด์ ์ฌ์ฉํ
์ ์์ด, ํน์ ๊ฒฝ๋ก๋ ํจํด์ ๋ํด ์ ๋ถ include
, exclude
๋ฅผ ์ ์ฉํ ์ ์๋ค.
์ฐ์ ์์
- ์๋ฌด๋ฐ ์ค์ ์ ํ์ง ์์ผ๋ฉด ๊ธฐ๋ณธ์ ์ผ๋ก
node_modules
,bower_components
,jspm_packages
,<outDir>
4๊ฐ๋ฅผ ์ ์ธํ๊ณ ๋ชจ๋ ์ปดํ์ผํ๋ค. exclude
์ค์ ์ ํ๋ฉด ์ด๊ฒ์ ์ ์ธํ๊ณ ๋ชจ๋ ์ปดํ์ผํ๋ค. 1๋ฒ์ ๊ธฐ๋ณธ ์ ์ธ ํญ๋ชฉ์ ๋ณ๋๋ก ์ง์ ํด์ฃผ์ง ์์๋ ๊ธฐ๋ณธ์ ์ผ๋ก ์ ์ธ๋๊ธฐ ๋๋ฌธ์ ์ ๊ฒฝ๋ก ์ธ ์ถ๊ฐ๋ก ์ ์ธํ ํ์ผ ๋๋ ๊ฒฝ๋ก๋ง ๋ชฉ๋ก์ ์์ฑํ๋ฉด ๋๋ค.include
์ค์ ์ ํ๋ฉด ์ด๊ฒ๋ง ์ปดํ์ผํ๋ค. ๋จ,<outDir>
์ ํฌํจ์ํค๋๋ผ๋ ๊ฐ์ ๋ก ์ ์ธ๋๋ค.- ์ฐ์ ์์๋
files
>exclude
>include
์ด๋ค.files
์ ์กด์ฌํ๋ฉด,exclude
์ ํฌํจ๋์ด ์๋๋ผ๋ ์ปดํ์ผ๋๋ฉฐ,include
์ ํฌํจ๋์ด ์๋๋ผ๋exclude
์ ํฌํจ๋๋ฉด ์ปดํ์ผ์์ ์ ์ธ๋๋ค.
4. references
{
"references": [
{ "path": "./path/to/project1" },
{ "path": "./path/to/project2" }
]
}
package.json
์ด ์ธ๋ถ ํจํค์ง์ ์์กด์ฑ์ ์ค์ ํ๋ ๋ฐ ์ฌ์ฉ๋๋ค๋ฉด, tsconfig.json
์ TypeScript ํ๋ก์ ํธ ๊ฐ ์์กด์ฑ๊ณผ
๋น๋ ์์๋ฅผ ์ค์ ํ๋ ๋ฐ ์ฌ์ฉ๋๋ค. ์ฌ๋ฌ ํ๋ก์ ํธ๋ฅผ ๋ชจ์ ํ๋์ ํ๋ก์ ํธ๋ก ๊ตฌํํ ๊ฒฝ์ฐ ์ด ์ค์ ์ ์ง์ ํ๋ฉด ์ปดํ์ผ๋ฌ๊ฐ ๋ณ๊ฒฝ๋
ํ๋ก์ ํธ๋ง ์ฌ์ปดํ์ผ ํด ๋น๋ ์๊ฐ์ ์ต์ ํ ํ ์ ์๋ค.
5. compilerOptions
compilerOptions ๋ TypeScript ์ปดํ์ผ์ ๊ด๋ จ๋ ์ค์ ์ ๋ค๋ฃจ๊ธฐ ๋๋ฌธ์ ๊ฐ์ฅ ๋ง์ ํ๋กํผํฐ๊ฐ ์กด์ฌํ๋ค. ๋ฐ๋ผ์ ๋ฐ๋ก ์๋ compilerOptions ์์ ๋ณ๋๋ก ๋ค๋ฃจ๋๋ก ํ๋ค.
3. tsconfig schema - compilerOptions
1. target / lib
target
{
"compilerOptions": {
"target": "ES5"
}
}
JavaScript ๋ฅผ ์ฌ์ฉํ ๋๋ ๋ฐฐํฌ๋ฅผ ํ๊ธฐ ์ ES ๋ ๋ฒจ์ ์ด๋๊น์ง ๋ด๋ ค ๋ฐฐํฌํ ์ง babel
๊ฐ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํด ๋ณํ,
๋ฐฐํฌํ์๋ค. ํ์ง๋ง TypeScript ๋ ํญ์ ๋ฐฐํฌ ์ JavaScript ๋ก ๋ณํํด์ผํ๊ธฐ ๋๋ฌธ์ babel
๊ณผ ๊ฐ์ ๋ณ๋์
๋ผ์ด๋ธ๋ฌ๋ฆฌ ์์ด ์ง์ ๋ณํํ ํ๊ฒ์ ์ค์ ํ๊ณ ์ปดํ์ผํ๋ค. ์ด๊ฒ์ ์ค์ ํ๋ ๊ฒ์ด ๋ฐ๋ก target
์ต์
์ด๋ค.
- ES3
- ES5
- ES6 / ES2015
- ES2016
- โฆ
- ES2022
- ESNext
๋ฅผ ์ค์ ํ ์ ์์ผ๋ฉฐ, ESNext
๋ latest, last ์ ๊ฐ์ ์๋ฏธ๋ก ์ฌ์ฉ๋๋ค. ํญ์ ์ต์ ๋ฒ์ ์ ํ๊ฒ์ผ๋ก ํ๋ค.
๋ณดํต Node ์๋ฒ์์๋ ํ์์ ๋ฐ๋ผ ๋ฒ์ ์ ์ฌ๋ฆฌ์ง๋ง ํ๋ก ํธ์๋๋ ๋ธ๋ผ์ฐ์ ํธํ์ฑ ๋ฌธ์ ๋ก โES2015โ(=ES6)๋ฅผ ํ์ค์ผ๋ก ์ฌ์ฉํ๋ค.
lib
{
"compilerOptions": {
"lib": ["ESNext", "DOM"]
}
}
์ปดํ์ผ๋ฌ๊ฐ ์ฌ์ฉํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ง์ ํ๋ ๊ฒ์ผ๋ก ๋๋ถ๋ถ target
์ ๋ฐ๋ผ default ๋ก ์ค์ ๋๋ lib
๊ฐ ์๊ธฐ ๋๋ฌธ์ ์ง์
์ค์ ํ ํ์๋ ๊ฑฐ์ ์๋ค.
- ES3:
lib.d.ts
- ES5:
dom
,es5
,scripthost
- ES6:
dom
,es6
,dom.iterable
,scripthost
๋ฅผ ๊ธฐ๋ณธ์ผ๋ก ์ฌ์ฉํ๋ค. ์ง์ ์ค์ ์ ํ๋ก ํธ์๋์์๋ ์ ๋ DOM
์ด ๋๋ฝ๋์ด์๋ ์ ๋๋ค.
2. module
{
"compilerOptions": {
"module": "ESNext"
}
}
๋ชจ๋ ์์คํ
์ ์ง์ ํ๋ค. โCommonJSโ, โAMDโ, โES5โ, โESNextโ, โNodeโ, โNodeNextโ, โSystemโ ๋ฑ์ ์ง์ ํ ์
์์ผ๋ฉฐ ํ๋ก ํธ์๋๋ ๋ณดํต ESNext
๋ฅผ ์ฌ์ฉํ๋ค.
3. moduleResolution
{
"compilerOptions": {
"moduleResolution": "Node"
}
}
๋ชจ๋ ํด์ ๋ฐฉ์์ ์ง์ ํ๋ค. ์ผ๋ฐ์ ์ผ๋ก โNodeโ ์ โClassicโ ์ค์์ ์ ํ์ ํ๊ฒ ๋๋๋ฐ, โClassicโ ์ ์ ํํ๋ฉด ํ์ผ ๊ฒฝ๋ก์์
.ts
๊น์ง ์ ๋ถ ์
๋ ฅํด์ฃผ์ด์ผํ๋ค. Node
๋ฅผ ์ค์ ํด์ผ index.ts
์ .ts
๋ฅผ ์๋ตํ ์ ์๋ค.
4. esModuleInterop
{
"compilerOptions": {
"esModuleInterop": true
}
}
ESM ๋ชจ๋ ๋ฐฉ์ ํธํ์ฑ์ ํ์ฑํํ๋ค. CommonJS
๋ฐฉ์์ export ์๋ default ๋ด๋ณด๋ด๊ธฐ๊ฐ ์๋ค. CommonJS
์ ESM
๋ฐฉ์์
import
, export
Syntax ๊ฐ ์กฐ๊ธ์ฉ ๋ค๋ฅธ๋ฐ, ์ด๋ฅผ ๊ตฌ๋ถํ์ง ์๊ณ ์ฌ์ฉํ ์ ์๋๋ก ํธํ์ฑ์ ๋ณด์ฅํด์ฃผ๋ ์ค์ ์ด๋ค.
5. isolateModules
{
"compilerOptions": {
"isolatedModules": true
}
}
๋ชจ๋ ํ์ผ์ ๋ชจ๋๋ก ์ปดํ์ผํ๋ค. ์ด ์ค์ ์ true
๋ก ํ ๊ฒฝ์ฐ ๋ชจ๋ ํ์ผ์ import
๋๋ export
๋ฅผ ํ๋ ์ด์ ํฌํจํด ๋ชจ๋์ด
๋๋๋ก ๊ฐ์ ๋๋ค. ๋ง์ฝ ์ด ์ค์ ์ ํ์ฑํ ํ์ ๊ฒฝ์ฐ import/export ๊ฐ ํ์ํ์ง ์๋ค๋ฉด export {}
๋ฅผ ์ ์ด์ฃผ์ด์ผ ๋ชจ๋๋ก ์ธ์ํด
์ปดํ์ผ ์๋ฌ๊ฐ ๋ฐ์ํ์ง ์๋๋ค.
6. baseUrl / paths
baseUrl
๋ชจ๋ ํด์์ ์ฌ์ฉํ ๊ธฐ์ค ๊ฒฝ๋ก๋ฅผ ์ง์ ํ๋ค. ์ฝ๊ฒ ๋งํ๋ฉด import
์ ์ฌ์ฉํ ๊ธฐ๋ณธ ๊ฒฝ๋ก๋ฅผ ์ง์ ํ๋ ๊ฒ์ด๋ค.
๋ค์ ์์ ๋ /src/pages/members/Vip.ts
ํ์ผ์์ ์ธ๋ถ ๋ชจ๋์ ๊ฐ์ ธ์จ๋ค.
import styled from 'styled-components';
import Input from '../../components/Input';
import Button from '../../components/Button';
import Info from '../../components/user/Info';
import { isAdult } from '../../utils/calendar';
node_modules
๋ ๋ณ๋์ ๊ฒฝ๋ก๋ฅผ ์์ฑํ์ง ์์๋ ๋์ง๋ง ์ฌ์ฉ์๊ฐ ์์ฑํ ๋ชจ๋์ ์์ ๊ฐ์ด ์์ธํ ๊ฒฝ๋ก๋ฅผ ์์ฑํด์ผํ๋ค.
์ด๋ ํ๋ก์ ํธ๊ฐ ์ปค์ง๊ณ ๊ฒฝ๋ก๊ฐ ๋ณต์กํด์ง๋ฉด ์๋นํ ํผ๋์ค๋ฌ์์ง๋ค. ์ด๋ tsconfig.json
์ ๊ธฐ์ค์ผ๋ก ์ฌ์ฉํ๊ณ ์ ํ๋ ๊ธฐ๋ณธ ๋๋ ํ ๋ฆฌ ์์น๋ฅผ baseUrl
์ ์์ฑํ๋ฉด import
์ ๋ชจ๋์ ์๋๊ฒฝ๋ก ๋ฟ ์๋๋ผ ์ ๋๊ฒฝ๋ก๋ฅผ ์ฌ์ฉํ ์ ์๋ค(๋ฌผ๋ก , ์๋๊ฒฝ๋ก๋ ์ฌ์ฉ ๊ฐ๋ฅํ๋ค).
{
"compilerOptions": {
"baseUrl": "src"
}
}
import styled from 'styled-components';
import Input from 'components/Input';
import Button from 'components/Button';
import Info from 'components/user/Info';
import { isAdult } from 'utils/calendar';
paths
์ฝ๊ฒ ๋งํด alias
๋ค. baseUrl
์ด ๋ชจ๋ ํด์์ ์ฌ์ฉํ ๊ธฐ์ค ๊ฒฝ๋ก๋ง ์ง์ ํ๋ค๋ฉด, paths
๋ ์ข ๋ ์ธ๋ถํ ์ํค๊ธฐ ์ํด ์ฌ์ฉํ๋ค.
path ๋ ๊ธฐ๋ณธ์ ์ผ๋ก baseUrl ์ ์ํฅ์ ๋ฐ์ผ๋ฏ๋ก, baseUrl ์ ์ค์ ํ์ ๊ฒฝ์ฐ, ํด๋น ๊ฒฝ๋ก๋ฅผ ์๋ตํ๊ณ ์์ํ ์ ์๋ค.
์ ๊ฒฝ์ฐ src/components
๋์ components
๋ง ์์ฑํด๋ ๋๋ค๋ ๋ง์ด๋ค.
{
"compilerOptions": {
"baseUrl": "src",
"paths": {
"@components/*": ["components/*", "components/user/*"],
"@utils/*": ["utils/*"]
},
}
}
import styled from 'styled-components';
import Input from '@components/Input';
import Button from '@components/Button';
import Info from '@components/Info';
import { isAdult } from '@utils/calendar';
๋๋ depth 1 ์ ๊ฒฝ๋ก๋ง ์๋์ผ๋ก ๋ฑ๋ก์ํค๋ ค๋ฉด ๋ค์๊ณผ ๊ฐ์ด ์ฌ์ฉํ ์ ์๋ค.
{
"compilerOptions": {
"baseUrl": "src",
"paths": {
"@*": ["*"]
},
}
}
import styled from 'styled-components';
import Input from '@components/Input';
import Button from '@components/Button';
import Info from '@components/user/Info';
import { isAdult } from '@utils/calendar';
์ด ๊ฒฝ์ฐ import Info from '@components/user/Info';
๋ import Info from '@components/Info';
๋ก
์ถ์ฝํ ์ ์์์ ์ ์ํ๋ค. ๊ทธ๋ฆฌ๊ณ ๊ฐ์ธ์ ์ผ๋ก ์ด ๋ฐฉ๋ฒ์ ๊ถ์ฅํ์ง ์๋๋ค. *
๋ฅผ ์ฌ์ฉํ๋ค๋ณด๋
path ์ root ์ ์๋ ํ์ผ์ ๊ฐ์ ธ์ฌ ๊ฒฝ์ฐ ๊ฐํน ์ ๋๋ก ๋งคํ์ด ๋์ง ์๊ธฐ๋ ํ๊ณ style ๊ฐ์ ๋๋ ํ ๋ฆฌ๋ ๊ณ์ ์๋ฌ ๋งคํ์ด ๋๋ ๊ฒฝ์ฐ๊ฐ
๊ฐํน ๋ฐ์ํ๋ค. ๋ํ ๊ฐ๋ณ ๋ฑ๋กํ ๊ฒฝ์ฐ
import Input from '../../components/Input';
import Input from 'components/Input';
import Input from '@components/Input';
์ด 3๊ฐ์ง ๋ฐฉ๋ฒ ์ค ์ด๋ค ๊ฒ์ ์ฌ์ฉํด๋ ์๋ํ์ง๋ง, *
๋ก path ๋ฅผ ์ง์ ํ๋ ๊ฒฝ์ฐ @
์ ์ฌ์ฉํ ์ ๊ทผ ์ธ ์ฒซ ๋ฒ์งธ ์๋ ๊ฒฝ๋ก๋ ๋ ๋ฒ์งธ ์ ๋๊ฒฝ๋ก๋ฅผ
ํตํ ์ ๊ทผ์ ์๋ฌ๊ฐ ๋ฐ์ํ๋ค.
๋ํ tsconfig ์์น๋ก๋ถํฐ ๋ค๋ฅธ ๋๋ ํ ๋ฆฌ๋ก ๋ถ๋ฅ๋๋ ๊ฒฝ์ฐ ๋ค๋ฅธ ๋ชจ๋๋ก ๋ถ๋ฆฌํ๋ ๊ฒ์ผ๋ก ๋ณด์ธ๋ค.
/api/...
์ /src/...
๋ ๋๋ ํ ๋ฆฌ๊ฐ ์์ ๋ "baseUrl": "."
, "paths": { "@utils/*": ["src/utils/*"] }
๋ฅผ
์ค์ ํ์์๋ /api/...
ํ์ ๋ชจ๋์์๋ @utils/calendar
๋ ์๋ฌ๊ฐ ๋ฐ์ํ๋ค. ์๋๊ฒฝ๋ก๋ก ../src/utils/calendar
๋ก ์์ ํด์ผ
์ ์์ ์ผ๋ก ์๋ํ๋ค. ์ด ๋ถ๋ถ์ ๋ํด์๋ ๋ค์ commit log
๋ฅผ ์ฐธ๊ณ ํ๋๋ก ํ๋ค.
7. rootDirs / outDir / outFile
rootDirs
, outDir
, outFile
์ ๋ชจ๋ files, include, exclude ์ ๋ง์ฐฌ๊ฐ์ง๋ก
baseUrl
์ ์ํฅ์ ๋ฐ์ง ์๋๋ค. ์ด๊ฒ๋ค์ ๋ชจ๋ ์ปดํ์ผํ ๋์์ ์ค์ ํ๋ ํ๋กํผํฐ๋ก tsconfig.json
์ ๊ธฐ์ค์ผ๋ก ์ง์ ํ๋ค.
rootDirs / outDir
{
"compilerOptions": {
"rootDirs": ["src"],
"outDir": "dist"
}
}
์ปดํ์ผ ํ root ๋๋ ํ ๋ฆฌ์ ๊ทธ๊ฒ์ ์ถ๋ ฅํ ๋ชฉํ ๋๋ ํ ๋ฆฌ๋ฅผ ์ง์ ํ๋ค. outDir
์ ์ผ๋ฐ์ ์ผ๋ก โdistโ, โpublicโ, โoutโ๊ณผ ๊ฐ์
๊ฒฝ๋ก๋ฅผ ์ฌ์ฉํ๋ค.
rootDirs
์ files, include, exclude ์ ์ํฅ์ ๋ฐ๋๋ค. ๋ฐ๋ผ์
{
"include": [
"src/**/*.ts"
],
"exclude": [
"node_modules",
"**/*.spec.ts"
]
}
๋ include
, exclude
์ ํจ๊ป ์ฌ์ฉํ ๊ฒฝ์ฐ ๋ค์๊ณผ ๊ฐ์ด ์์ฑํ ์ ์๋ค.
{
"compilerOptions": {
"rootDirs": ["src"],
"outDir": "dist"
},
"include": [
"**/*.ts"
],
"exclude": [
"node_modules",
"**/*.spec.ts"
]
}
rootDirs
๋ก ์ปดํ์ผ์ ํ root ๋๋ ํ ๋ฆฌ๊ฐ src
๋ก ์ง์ ๋์๊ธฐ ๋๋ฌธ์ include
์ ํจํด์ src
๊ฒฝ๋ก๋ฅผ ํฌํจํ ํ์๊ฐ ์๋ค.
outFile
{
"compilerOptions": {
"outFile": "dist/main.js"
}
}
module
์ด AMD
๋๋ System
๊ฐ์ ํํ์ผ ๋ ๋ชจ๋ JavaScript ์ฝ๋๋ฅผ ๋จ์ผ ํ์ผ๋ก ์ปดํ์ผํ ์ ์๋๋ก ํ๋
์ต์
์ผ๋ก ์ผ๋ฐ์ ์ผ๋ก CommonJS
, ES6
๊ฐ์ ํํ๋ก ์ฌ์ฉํ ๋๋ ์ฌ์ฉ์ด ๋ถ๊ฐ๋ฅํ๋ค.
8. typeRoots / types
typeRoots
{
"compilerOptions": {
"typeRoots": [
"node_modules/@types",
"utils/types",
"vendor/types"
]
}
}
JavaScript ๋ก ์์ฑ๋ ๋ชจ๋์ ๋ํด ์ปดํ์ผ๋ฌ๊ฐ ์ฐธ์กฐํ ํ์
์ ์ธ d.ts
๊ฒฝ๋ก๋ฅผ ์ง์ ํ๋ค. node_modules/@types
๋๋ ํ ๋ฆฌ๋
ํน๋ณํ ๊ฒฝ๋ก๋ก ๋ฏธ์ง์ ์ ๊ธฐ๋ณธ๊ฐ์ผ๋ก ์ฌ์ฉ๋๋ค. ํ์ง๋ง ์ด ๊ท์น์ ๋ฐ๋ฅด์ง ์๋ JavaScript ๊ธฐ๋ฐ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ์ ํธ์ ์ํด d.ts
ํ์ผ์
์ ๊ณตํด์ผ ํ ๊ฒฝ์ฐ ์ด ํ๋กํผํฐ์ ๋ฐฐ์ด๋ก ์ง์ ํ๋ค. ์ด๋ ์ฃผ์ํด์ผ ํ ๊ฒ์ด node_modules/@types
๋ฅผ ์ ์ธํ๊ณ ๋ฐฐ์ด์ ์์ฑํ๋ฉด
typeRoots
๊ฐ์ด ์ ๊ณต๋์๊ธฐ ๋๋ฌธ์ ๊ธฐ๋ณธ๊ฐ์ด ์ฌ์ฉ๋์ง ์์ผ๋ฏ๋ก ํฌํจ์์ผ์ฃผ์ด์ผํ๋ค.
types
JavaScript ๋ชจ๋์ ์ฌ์ฉํ ๋ typeRoots
์์ d.ts
๋ฅผ ๊ฒ์ํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ๊ฐ๋ณ๋ก ์ง์ ํ๋ค. ๋ฏธ์ง์ ์ ๋ชจ๋ JavaScript
๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋ํด d.ts
๋ฅผ ๊ฒ์ํ๋ค.
{
"compilerOptions": {
"types": [
"node",
"lodash",
"express"
]
}
}
์์ ๊ฐ์ด ์ง์ ํ ๊ฒฝ์ฐ node
, lodash
, express
3๊ฐ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋ํด์๋ง d.ts
๋ฅผ ๊ฒ์ํ๋ค. ๋ง์ฝ types
๋ฅผ
๋ฏธ์ง์ ํ์ง ์๊ณ "types": []
์ ๊ฐ์ด ๋น ๋ฐฐ์ด๋ก ์ง์ ํ ๊ฒฝ์ฐ d.ts
๋ฅผ ๊ฒ์ํ๋ ํ์
์์คํ
์ ์ด์ฉํ์ง ์๊ฒ ๋ค๋ ์๋ฏธ๊ฐ ๋๋ค.
ํน๋ณํ ๊ฒฝ์ฐ๊ฐ ์๋๋ผ๋ฉด ์ด ํ๋กํผํฐ๋ ๋ฏธ์ง์ ์ํ๋ก ๋๋ ๊ฒ์ด ์ข๋ค.
TypeScript ์์ ์ด๋ฏธ์ง๋ฅผ import ๊ตฌ๋ฌธ์ด ์ ๋๋ก ์ธ์ํ์ง ๋ชปํ๋ ๋ฌธ์ ๊ฐ ์๋ค. ์ด๊ฒ์ root ๊ฒฝ๋ก์
d.ts
ํ์ผ์ ๋ง๋ค์ดdeclare
๋ฅผ ํตํด ์ด๋ฏธ์ง๋ฅผ ๋ชจ๋๋ก ์ ์ํด์ฃผ๋ฉด ๋๋ค.
- images.d.ts
declare module "*.jpg"; declare module "*.jpeg"; declare module "*.png"; declare module "*.gif"; declare module "*.webp";
typeRoots
,types
๋ฅผ ๋ฏธ์ง์ ์ํ๋ก ๋ ๊ฒฝ์ฐ root ๊ฒฝ๋ก์ ์์ฑํimages.d.ts
๋ฅผ ์๋์ผ๋ก ์ธ์ํ๋ฏ๋ก ๋ฐ๋ก ์์ ํด์ค ํ์๋ ์๋ค.
9. strict
{
"compilerOptions": {
"strict": true
}
}
strict
๋ ๋ฐ๋์ true
๋ก ์ค์ ํ๋ ๊ฒ์ ๊ธฐ๋ณธ์ผ๋ก ํ๋ค. ์ด๊ฒ์ ํ์ฑํ ํ๋ฉด ์ปดํ์ผ ๋ JavaScript ํ์ผ ์๋จ์
"use strict";
๊ฐ ํฌํจ๋ ๊ฒ์ด๋ค. ์ด ์ต์
์ ์ Type System ์์ ์ดํด๋ณด์๋,
- noImplicitAny
- noImplicitThis
- strictNullChecks
- strictFunctionTypes
- strictPropertyInitialization
- strictBindCallApply
- alwaysStrict
TypeScript ๊ฐ ์ข ๋ Type-Safe ํ ์ฝ๋๋ฅผ ์์ฑํ๋๋ก ๋๋ ๋๋ถ๋ถ์ ์ต์ ์ ์ผ๋ ๊ฒ์ ์๋ฏธํ๋ค(์ผ๋ถ ํ์ฑํ ๋์ง ์๋ ์์ธ ์กด์ฌ).
1 ) noImplicitAny
function noImplicitAny(x) {
return x;
}
๋ช
์์ ์ธ any
๋ ํ์ฉ๋์ง๋ง, ํ์
์ถ๋ก ์ ์ํ any
๋ ํ์ฉํ์ง ์๋๋ค(๊ทธ๋ ๋ค๊ณ ์ฌ์ฉํ๋ผ๋ ๊ฒ์ ์๋๋ค ํ์์
unknown ์ ์ฌ์ฉํ ๊ฒ).
function noImplicitAny(x: any) {
return x;
}
2 ) noImplicitThis
function greet(age: number) {
console.log(`Hello, ${this.name}! I'm ${age} years old`);
}
์ด๋ฐ์์ this
๊ฐ ์๋ ํํ๋ ์๋ฌ๋ก ๊ฐ์ฃผ๋๋ค. JavaScript ์ this
๋ ์๋ ์ฌ์คํ๊ธฐ ๋๋ฌธ์ ๋ณํ์ ์๋ชป๋
this
๋ฅผ ์ฌ์ฉํ๊ฒ ๋๋ ๊ฒ์ ๋ง๊ธฐ ์ํด ๋ช
์์ ์ผ๋ก ์ ํํ ์ ๋ณด์ this
๋ฅผ ์ ๊ณตํด์ผํ๋ค.
์ด๊ฒ์ Python ์ ๋ฌธ๋ฒ๊ณผ ์ ์ฌํ๊ฒ ์ฒซ ๋ฒ์งธ Parameter ๋ก ์๊ธฐ ์์ ์ ์ ๊ณตํด์ผํ๋ฉฐ, ์๊ธฐ ์์ ์ ํ์ ์ ๋ณด๋ฅผ ํฌํจํด์ผํ๋ค.
function greet(this: { name: string }, age: number) {
console.log(`Hello, ${this.name}! I'm ${age} years old`);
}
๋ฐ๋ผ์ Constructor Function ์ญ์ ํ์
๋ง ๋ถ์ฌ ์ฌ์ฉํ๋ ค ํ๋ฉด ์๋ฌ๊ฐ ๋ฐ์ํ๋ฏ๋ก ๋ช
ํํ this
๋ฅผ ์ ๊ณตํด์ผํ๋ค.
interface IPerson {
name: string;
age: number;
greet(): void;
}
function Person(this: IPerson, name: string, age: number) {
this.name = name;
this.age = age;
this.greet = function () {
console.log(
`Hello, my name is ${this.name} and I'm ${this.age} years old.`
);
};
}
์ฌ์คโฆ ์ด์ ๋๋ก boiler-code ๋ฅผ ๋ง์ด ๋ง๋ค๊ฑฐ๋ฉด ์ฐจ๋ผ๋ฆฌ Class
๋ฌธ๋ฒ์ ์ฌ์ฉํ๊ฑฐ๋ ์์ ํ ํจ์ํ
์ผ๋ก ์ฌ์ฉํ๋ ๊ฒ์ด ๋ซ๋ค.
class Person {
constructor(private name: string, private age: number) {}
greet() {
console.log(
`Hello, my name is ${this.name} and I'm ${this.age} years old.`
);
}
}
๋๋
function Person(name: string, age: number) {
let _name = name;
let _age = age;
function greet() {
console.log(`Hello, my name is ${_name} and I'm ${_age} years old.`);
}
return {
greet,
};
}
3 ) strictNullChecks
์ Make TypeScript more Strictly ์์ ์ด๋ฏธ ํ ๋ฒ ์ดํด๋ณด์๋ฏ์ด
TypeScript ์ ๋ชจ๋ ํ์
์ด ๊ธฐ๋ณธ์ ์ผ๋ก null
๊ณผ undefined
๋ฅผ ํฌํจํ๊ธฐ ๋๋ฌธ์ ์ด๊ฒ์ ์ ์ธ์์ผ์ฃผ๋ ์ต์
์ด๋ค.
์ด๊ฑธ ์ฒดํฌํด์ฃผ์ง ์์ผ๋ฉด ๋ชจ๋ ํ์
์ด ์ฌ์ค์ Optional
ํ์
์ด ๋์ด๋ฒ๋ฆฐ๋ค. ํ์์ ์ํด Union
ํ์
์ ์ด์ฉํด
Optional
์ ๋ง๋๋ ๊ฒ์ด ์๋ ๋ชจ๋ ํ์
์ด Optional ์ด ๋๋ ๊ฒ์ ๊ฒฐ๊ตญ JavaScript ์ ํฐ ์ฐจ์ด๊ฐ ์์ด์ง๋
๊ฒ์ด๋ค.
4 ) strictFunctionTypes
Type Compatibility ์์ ์ดํด๋ณธ ๊ฒ์ฒ๋ผ TypeScript ๋ ๋ค๋ฅธ ์ธ์ด์ ๋ฌ๋ฆฌ ๊ธฐ๋ณธ์ ์ผ๋ก Sub-Type ์ด Super-Type ์ ์์ ํธํํ๋ ๊ฒ์ด ๊ฐ๋ฅํ ๋ฌธ์ ๋ฅผ ์ ๊ฑฐํ๋ ์ต์ ์ด๋ค.
ํจ์์ arguments ์ ๋ํ ํ์ ๊ฒ์ฌ๋ฅผ ๊ฐํํด ๋ค๋ฅธ ์ธ์ด์ ๋ง์ฐฌ๊ฐ์ง๋ก Super-Type ์ด Sub-Type ์ ํ์ ํธํ ํ๋ ๊ฒ๋ง ํ์ฉํ๋๋ก ํ๋ค(๋จ์ํ parameter ์ argument ํ์ ์ ๊ฒ์ฌํ๋ ๊ฒ์ ํด๋น ์ต์ ํ์ฑํ์ ๋ฌด๊ดํ๊ฒ ๊ธฐ๋ฅํ๋ค. ์ด๊ฒ์ Super-Type ๊ณผ Sub-Type ์ ์ฌ๋ฐ๋ฅธ ๊ด๊ณ๋ฅผ ๊ฒ์ฌํ๊ธฐ ์ํ ์ค์ ์ด๋ค).
5 ) strictPropertyInitialization
class Person {
private name: string;
private age: number;
constructor() { }
greet() {
console.log(
`Hello, my name is ${this.name} and I'm ${this.age} years old.`
);
}
}
์ ๊ฐ์ด Class ์ Properties ๋ฅผ ์ด๊ธฐํ ํ์ง ์์ ๊ฒฝ์ฐ ์๋ฌ๋ฅผ ๋ฐ์์ํค๋ ์ต์ ์ผ๋ก, TypeScript ์ Class ๋ฅผ ์ข ๋ Class ๋ต๊ฒ ๋ง๋ค์ด์ฃผ๋ ์ต์ ์ด๋ค.
๋ฐ๋์ ์์ฑ์๋ฅผ ์ฌ์ฉํด ์ด๊ธฐํ๋ฅผ ์์ผ์ฃผ๊ฑฐ๋
class Person {
constructor(private name: string, private age: number) {}
greet() {
console.log(
`Hello, my name is ${this.name} and I'm ${this.age} years old.`
);
}
}
๊ธฐ๋ณธ๊ฐ์ ์ ๊ณตํด์ผํ๋ค.
class Person {
private name: string = 'John';
private age: number = 23;
constructor() {}
greet() {
console.log(
`Hello, my name is ${this.name} and I'm ${this.age} years old.`
);
}
}
Classes ์ ์ด๊ธฐํ๋ ์๋ฌ์ ์ํด ์คํจํ ์๋ ์์ง๋ง, ์๋์ ์ผ๋ก ์ง์ฐ์์ผ์ผ ํ ํ์๊ฐ ์๋ ๊ฒฝ์ฐ๋ ์๋ค. ์ด๊ธฐํ๋ฅผ ํ๋
๋์ ๊ฐ์ ์ค์ ํ ์ ์์ด Optional Property Types ๋ฅผ ํ์๋ก ํ๋ ๊ฒฝ์ฐ๋ค. TypeScript ์ญ์ ์ด๋ฅผ ์ง์ํ๋ฉฐ,
?
๋๋ !
๋ฅผ ์ ์ ํ ์ฌ์ฉํด Classes ๋ฅผ ์์ฑํ๋ฉฐ, Properties ์ ์ด๊ธฐํ๋ฅผ ์ง์ฐ์ํฌ ์ ์๋ค. ๋ฌผ๋ก , ์ด์ ๋ํ
์ฑ
์์ด ๊ฐ๋ฐ์์๊ฒ ์ฃผ์ด์ง๋ค(?
๋ constructor ์ ๋จ์ถํ์ผ๋ก ์์ฑํ ์ ์์ง๋ง !
๋ constructor ๋ฅผ ํตํด ์์ฑํ ์ ์๋ค).
class Person {
private name!: string;
constructor(name: string, private age?: number) {}
async init(name: string, age?: number) {
this.name = name;
this.age = age;
}
greet() {
console.log(
`Hello, my name is ${this.name} and I'm ${this.age} years old.`
);
}
}
6 ) strictBindCallApply
Function
์ ๋ด์ฅ ํจ์์ธ bind
, call
, apply
๋ฅผ ์ฌ์ฉํ ๋ ํจ์ ํธ์ถ๊ณผ ๋ฌ๋ฆฌ ํ์
์ฒดํฌ๋ฅผ ํ์ง ์๋๋ค.
์ด ์ค์ ์ ํ์ฑํ ์์ผ์ผ์ง๋ง ์๊ฒฉํ ์ฒดํฌ๋ฅผ ํ๋ค.
function sum(a: number, b: number): number {
return a + b;
}
sum('1', '2'); // error
sum.call(null, '1', '2'); // OK!
์ด ํ๋กํผํฐ๋ฅผ ํ์ฑํ ์ํค๋ฉด ์ด์ bind
, call
, apply
์๋ ์๊ฒฉํ ํ์
๊ฒ์ฌ๊ฐ ์ถ๊ฐ๋๋ค.
sum('1', '2'); // error
sum.call(null, '1', '2'); // error
7 ) alwaysStrict
์ปดํ์ผ๋๋ ๋ชจ๋ JavaScript ํ์ผ ์๋จ์ "use strict"
๋ฅผ ํฌํจ์์ผ ๋ฐํ์ ์์ง์ด ์ฝ๋๋ฅผ strict
๋ชจ๋๋ก ๋ถ์ํ๋๋ก
ํ๋ ์ต์
์ด๋ค.
5. Interfaces ๐ฉโ๐ป
TypeScript ์ Interfaces ๋ JavaScript ์ ์กด์ฌํ์ง ์๊ธฐ ๋๋ฌธ์ ๋ค๋ฅธ ์ธ์ด์ ๋ฌ๋ฆฌ Runtime ์ด ์๋ ์ค์ง Compile-time ์๋ง ์ฌ์ฉ๋๋ค. ์ฆ, ์ปดํ์ผ ๊ณผ์ ์์ ์ ๊ฑฐ๋์ด ์ค์ ๋ฐฐํฌ๋๋ ์ฝ๋์๋ ๋จ์ง ์๊ฒ ๋๋ ๊ฒ์ด๋ค. ๊ธฐ๋ณธ์ ์ผ๋ก ํ๊ณ ์ ํ๋ ์ญํ ์ด๋ ๋ชฉ์ ์ด ๋ค๋ฅธ ํ๋ก๊ทธ๋๋ฐ ์ธ์ด์ฒ๋ผ ์ฌ์ฉํ๊ธฐ ์ํจ์ด๊ธฐ ๋๋ฌธ์ ํฌ๊ฒ ๋ค๋ฅด์ง ์์ง๋ง TypeScript ๋ง์ ํน์ง์ ์์๋ฌ์ผํ๋ค.
1. Optional Properties
ํํ ์ ํ๊ธฐ ์ฌ์ด ๋ฐฉ๋ฒ์ ๋ค๋ฅธ ์ธ์ด์ ๋์ผํ๊ฒ Properties ์์ฒด๋ฅผ Optional
๋ก ์ค์ ํ๋ ๊ฒ์ด๋ค.
interface Person {
readonly country: string;
name: string;
age?: number
}
๊ทธ๋ฆฌ๊ณ ๋ค๋ฅธ ๋ฐฉ๋ฒ์ Index Signatures ๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด๋ค.
interface Person {
readonly country: string;
name: string;
age?: number;
[index: string]: any;
}
์๊ธด ๊ฒ๊ณผ ์ด๋ฆ์ ๋ณด๋ฉด Swift Subscripts ์ ์ ์ฌํ ๊ฒ ๊ฐ์ง๋ง ๋ค๋ฅด๋ค. ์ผ๋จ ์ด๊ฒ์ interface
์์ ๋ช
์ฌํ์.
์ฆ, ๊ตฌํ์ฒด๊ฐ ์๋๋ผ๋ ์๋ฏธ์ด๋ค.
2. Index Signatures
์ฐ์ , Index Signature
๋ number
, string
, symbol
์ ํ์
์ผ๋ก Index Type ์ผ๋ก ๊ฐ์ง ์ ์๋ค.
Number Index Signatures
number
๋ฅผ index signature ๋ก ์ฌ์ฉํ๋ฉด ์ด property ๋ iterable ์ด ๊ฐ๋ฅํ ํ์
์ ์๋ฏธํ๋ค.
interface StringArray {
[index: number]: string;
}
const stringArray: StringArray = ['a', 'b', 'c', 'd'];
const anotherStringArray: StringArray = 'qerty';
console.log(stringArray[1], anotherStringArray[2]); // b r
interface NumberArray {
[index: number]: number;
}
const numberArray: NumberArray = [1, 2, 3, 4];
console.log(numberArray[1], numberArray[2]); // 2 3
interface Dog extends Animal {
breed: string;
}
interface DogArray {
[index: number]: Dog;
}
const dog1: Dog = { name: '๋๋ถ', breed: 'Labrador' };
const dog2: Dog = { name: '์น์ฆ', breed: 'Husky' };
const dog3: Dog = { name: 'ํธ๋ฉ', breed: 'Poodle' };
const dogArray: DogArray = [dog1, dog2, dog3];
์ฌ๊ธฐ์ ์ค์ํ ๊ฒ์ Index Signature ์ key ํ์ ์ด number ๋ผ๋ ๊ฒ์ด์ง ํด๋น ์ธํฐํ์ด์ค์ parameter ํ์ ์ด number ๊ฐ ์๋๋ผ๋ ๊ฒ์ด๋ค. ์ข ๋ ์์ธํ ์ดํด๋ฅผ ์ํด ์๋ String Index Signatures ๋ฅผ ๋ณด์.
String Index Signatures
interface NumberDictionary {
[index: string]: number;
volunteers: number;
}
์ ๊ฐ์ด Index Signature ๋ก ์์ฑํ parameter ์ ํ์ ์ด number ์ด๋ฏ๋ก, ๋ค๋ฅธ properties ์ญ์ number ํ์ ์ด์ด์ผํ๋ค.
interface NumberDictionary {
[index: string]: number;
programName: string; // type error
}
์ด๊ฒ์ ๋ถ๊ฐ๋ฅํ ์ ์๋ค. someDictionary['foo']
๋ฅผ ํ ๊ฒฐ๊ณผ๊ฐ number ์ธ๋ฐ programName ์ด string
์ด ๋๋ ๊ฒ์ด ๋ถ๊ฐ๋ฅํ๊ธฐ ๋๋ฌธ์ด๋ค. ์ด๊ฒ์ด ๊ฐ๋ฅํ๋ ค๋ฉด ์๋ ๊ฐ์ด Index Signature ๋ก ์์ฑํ parameter ์ ํ์
์ญ์
string ์ด ๋์ด์ผ ํ๋ค.
interface StringDictionary {
[index: string]: string;
programName: string;
}
ํ์ง๋ง, Dictionary Type ์ฆ, TypeScript ์์ Object ๋ string, number, etcโฆ ์ ๊ฐ์ด
๋ค์ํ ํ์
์ properties ๋ฅผ ์ ์ฅํ ์ ์๋ ์ปจํ
์ด๋๋ค. ์ด๊ฒ์ ์ํด ์ฐ๋ฆฌ๋ Index Signatures ๊ฐ ๊ฐ์ง ์ ์๋
ํ์
์ Union Type
์ ์ฌ์ฉํด ๋ณต์ ํ์ฉ์ ํ ์ ์๋ค.
interface VolunteerRecruit {
[index: string]: number | string;
volunteers: number;
programName: string;
}
const africaRecruit: VolunteerRecruit = {
volunteers: 10,
programName: '2023 12์ ์ํ๋ฆฌ์นด ์์๋ด์ฌ',
};
console.log(
`${africaRecruit['programName']}์ ์ง์์ ์๋ ${africaRecruit['volunteers']}๋ช
์
๋๋ค.`
);
2023 12์ ์ํ๋ฆฌ์นด ์์๋ด์ฌ์ ์ง์์ ์๋ 10๋ช
์
๋๋ค.
์ฌ๊ธฐ์ ์ค์ํ ๊ฒ ์ญ์ Index Signature ์ key ํ์ ์ด string ์ด๋ผ๋ ๊ฒ์ด์ง ํด๋น ์ธํฐํ์ด์ค์ parameter ํ์ ์ด string ์ด ์๋๋ผ๋ ๊ฒ์ด๋ค.
์ฆ, Index Signatures ๊ฐ number ๋ผ๋ ๊ฒ์
foo[3]
๊ณผ ๊ฐ์ด ์ฌ์ฉํ๊ธฐ ์ํ ๊ฒ์ผ๋ก Array ์ ๊ฐ์Iterable
ํ์ ์ ์ ์ํ๊ธฐ ์ํ ๊ฒ์ด๋ผ ๋ณด๋ฉด ๋๋ค. ๋ง์ฐฌ๊ฐ์ง๋ก Index Signatures ๊ฐ string ์ด๋ผ๋ ๊ฒ์bar['baz']
์ ๊ฐ์ด ์ฌ์ฉํ๊ธฐ ์ํ ๊ฒ์ผ๋ก Object ์ ๊ฐ์Key-Value
ํ์ ์ ์ ์ํ๊ธฐ ์ํ ๊ฒ์ด๋ผ ๋ณด๋ฉด ๋๋ค.
๋ง์ฝ JavaScript ์ Object, Java ์ Map, Swift ์ Dictionary ์ [String: Any]
์ ๊ฐ์ ๋ฐฉ์์ผ๋ก ๋ชจ๋ ๋ฐ์ดํฐ๋ฅผ
์ ์ฅํ ์ ์๋ Key-Value
Types ๋ก ์ฌ์ฉํ๊ณ ์ ํ๋ค๋ฉด unknown
์ ์ฌ์ฉํด ๋ชจ๋ ํ์
์ Dynamic ์ผ๋ก ๋ฐ์ ์ ์๋ค.
interface VolunteerRecruit {
[index: string]: unknown;
volunteers: number;
programName: string;
}
Symbol Index Signatures
symbol ์ Index Signature ์ ์ฌ์ฉํ ์ผ์ด ๋ง์ ๊ฒ ๊ฐ์ง๋ ์๋ค. string ๊ณผ ์ ์ฌํ๊ฒ ์ฌ์ฉํ ์ ์์ผ๋ฉฐ, string ์ ํตํ ์ ๊ทผ์ ๋ง๊ธฐ ์ํด ์ฌ์ฉํ ์ ์๋ค.
interface Member {
[index: symbol]: string; // for name
age: number;
}
const gildongId = Symbol('id8784');
const member: Member = {
[gildongId]: 'ํ๊ธธ๋',
age: 28,
};
// console.log(member['id8784']); // error
console.log(member[gildongId]); // ํ๊ธธ๋
3. Type Alias & Interface
TypeScript ์์ interface
์ type
์ ๋ง์ ๊ณณ์์ ํผ์ฉ๋๋ฉฐ ์๋ก ๋ฐ๊พธ์ด ์ฌ์ฉํด๋ ๋๋ถ๋ถ ํธํ์ด ๊ฐ๋ฅํ๋ค.
Functions
type ArithmeticCalc = (lhs: number, rhs: number) => number;
let addTwoInts: ArithmeticCalc = (lhs: number, rhs: number) => lhs + rhs;
let multiplyTwoInts: ArithmeticCalc = (a: number, b: number) => a * b;
interface ArithmeticCalc {
(lhs: number, rhs: number): number;
}
let addTwoInts: ArithmeticCalc = (lhs: number, rhs: number) => lhs + rhs;
let multiplyTwoInts: ArithmeticCalc = (a: number, b: number) => a * b;
Array
type PersonList = string[];
const students: PersonList = ['Alice', 'Bob', 'Charlie'];
type
์ ๋ฌธ๋ฒ์ ๋ค๋ฅธ ์ธ์ด์ ํฌ๊ฒ ๋ค๋ฅด์ง ์๋ค.
interface PersonList {
[index: number]: string;
}
const students: PersonList = ['Alice', 'Bob', 'Charlie'];
interface
๋ ์ด๋ฅผ ์ํด ์์์ ๋ณธ Number Index Signatures ๋ฅผ ์ฌ์ฉํ๋ค.
Intersection
interface Breakfast {
breakfast: string;
}
interface Lunch {
lunch: string;
}
interface Dinner {
dinner: string;
}
๋ฅผ ํ์ฅํด ์ ํ์ ์ ๋ง๋ค์ด๋ณด์.
type DayMeal = Breakfast & Lunch & Dinner;
const todayMeal: DayMeal = {
breakfast: 'hamburger',
lunch: 'pizza',
dinner: 'burger',
};
interface DayMeal extends Breakfast, Lunch, Dinner {}
const todayMeal: DayMeal = {
breakfast: 'hamburger',
lunch: 'pizza',
dinner: 'burger',
};
Union Types
interface Bird {
fly(): void;
layEggs(): void;
}
interface Fish {
swim(): void;
layEggs(): void;
}
type PetType = Bird | Fish;
interface Pet extends PetType {} // error, TS2312
class Pet implements PetType {} // error, TS2422
- Union Types๋ Type Alias๋ก๋ง ํํ ๊ฐ๋ฅํ๋ค.
- Union Types๋ ์ธํฐํ์ด์ค์ extends ๋ ํด๋์ค์ implements ์ ์ฌ์ฉ๋ ์ ์๋ค.
type
์ด ํด๋์ค implements ์ ์ฌ์ฉ ๋ถ๊ฐ๋ฅํ ๊ฒ์ ์๋๋ค.type AnimalType = { name: string; color: string; kind: string; weight: number; }; class Animal implements AnimalType { name: string = 'Swan'; color: string = 'white'; kind: string = 'bird'; weight: number = 5; }
์ค์ง
Union Type
์ด ์ฌ์ฉ ๋ถ๊ฐ๋ฅํ ๊ฒ์ด๋ค.
Declaration Merging
์ด๋ฒ์ Union Types
์ ๋ฐ๋๋ก ์ธํฐํ์ด์ค๋ฅผ ํตํด์๋ง ๊ฐ๋ฅํ ๊ฒ์ ์๊ฐํ๋ค.
interface MergingInterface {
foo: string;
}
interface MergingInterface {
bar: string;
}
const something: MergingInterface = {
foo: 'yellow',
bar: 'blue',
};
๋์ผํ ์ด๋ฆ์ผ๋ก ๋ณต์์ ์ธํฐํ์ด์ค๋ฅผ ์ ์ธํ ์ ์์ ๋ฟ ์๋๋ผ ์๋์ผ๋ก ๋จธ์ง๊ฐ ๋๋ค. Type Alias ๋ ์ค๋ณต ์ ์ธ์ ํ์ฉํ์ง ์์ ์๋ฌ๊ฐ ๋ฐ์ํ๋ค.
์ธํฐํ์ด์ค์ ๋จธ์ง๋ HTML elements ๋ฅผ ํ์ฅํ๊ฑฐ๋ ํ ๋ ๊ธฐ์กด์ ์๋ ๊ฒ๋ ์ฌ์ฉํ๊ณ , ๋ด๊ฐ ์ถ๊ฐํ ๊ฒ๋ ์ฌ์ฉํ๋๋ก ํฉ์ณ์ผ ํ ๋ ์ ์ฉํ๊ฒ ์ฌ์ฉ๋๋ค.
6. Classes ๐ฉโ๐ป
1. Initialization
Classes ์ฉ๋๋ ๋ฌธ๋ฒ, ๊ธฐ๋ฅ์ ๋ค๋ฅธ ์ธ์ด์ ์ ์ฌํ๋ค. TypeScript ์ ๋ฌธ๋ฒ์ ํน์ง์ ์์ฃผ๋ก ์ดํด๋ณด์.
class Person {
name: string;
private age: number;
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
}
๋ ๋ค์๊ณผ ๊ฐ์ด ์ถ์ฝํด์ ํํ์ด ๊ฐ๋ฅํ๋ค.
class Person {
constructor(public name: string, private age: number) {}
}
2. Getters & Setters
class Person {
constructor(public name: string, private age: number) {}
get name(): string { return this.name; } // error, Duplicate identifier 'name'.
}
๊ธฐ๋ณธ์ ์ผ๋ก JavaScript ์ ES6 Classes ๋ฌธ๋ฒ์์ ์กด์ฌํ๋ Properties ์ ๋ํ Gatters
์ Setters
๊ฐ
์๋์ผ๋ก ์์ฑ๋๋ค. ๋ฐ๋ผ์ ๊ฐ๋ฐ์๊ฐ ๋ง๋ค๋ ค๊ณ ํ๋ฉด ์ค๋ณต ์๋ฌ๊ฐ ๋ฐ์๋๋ค. ๋ฉ์๋ ํํ๋ก ์ ์ํ์ง๋ง, ์ฌ์ค์ ์ด๊ฒ์
Computed Properties ์ ๊ฐ๊น์ด ํํ๋ค.
class Person {
constructor(
public _name: string,
private age: number,
private changeName = 0
) {}
get name(): string {
console.log(`Log: ${this._name}์ด ์กฐํ๋์์ต๋๋ค.`);
return this._name;
}
set name(value: string) {
console.log(`Log: ์ด๋ฆ์ด ${++this.changeName}๋ฒ ๊ฐ๋ช
๋์์ต๋๋ค.`);
this._name = value;
}
}
const p: Person = new Person('John', 30);
console.log(`์๋
ํ์ธ์. ์ ์ด๋ฆ์ ${p.name}์
๋๋ค.`);
p.name = 'Kevin';
Log: John์ด ์กฐํ๋์์ต๋๋ค.
์๋
ํ์ธ์. ์ ์ด๋ฆ์ John์
๋๋ค.
Log: ์ด๋ฆ์ด 1๋ฒ ๊ฐ๋ช
๋์์ต๋๋ค.
๋ํ ์ด๋ฅผ ์ ํ์ฉํ๋ฉด private(set)
๊ณผ ๊ฐ์ด ์ ๊ทผ ์ ์ด๋ฅผ ๋ค๋ฅด๊ฒ ์ค์ ํ ์ ์๋ค.
class SomeClass {
private(set) var id: String = ""
func setId(_ id: String) {
self.id = id
}
}
๋ ๋ค์๊ณผ ๊ฐ์ด ๊ตฌํํ ์ ์๋ค.
class SomeClass {
private _id: String = '';
get id(): String {
return this._id;
}
setId(id: String) {
this._id = id;
}
}
const someClass = new SomeClass();
someClass.id = 'A'; // error: Cannot assign to 'id' because it is a read-only property.
someClass.setId('A');
console.log(someClass.id); // A
3. Index Signatures in Classes
์ผ๋ฐ์ ์ผ๋ก ํ๋ก๊ทธ๋๋ฐ ์ธ์ด๊ฐ Dynamic Types ๋ฅผ ์ฌ์ฉํ๋ Dictionaries ์ ๊ฐ์ ํ์ ์ ๊ฐ๊ณ ์์ง๋ง Classes ์ ๊ฐ์ ํ์ ์ ์ ์ํ๊ณ ์ฌ์ฉํ ๋, ์ด๋ฌํ ํ์ ๋ค์ ์์ ์ properties ์ ๋ํ ๋์ ํ์ ์ ํ์ฉํ์ง ์๋๋ค. ๋ง์ฝ, Classes ๋ด๋ถ์ ๋์ ํ์ ์ ๊ฐ์ง ์ ์๋ Dictionary Type Properties ๋ฅผ ์ถ๊ฐํ๊ณ , ์ฌ๊ธฐ์ ๋์ ๋ฐ์ดํฐ๋ฅผ ๋ฃ์ด์ผํ๋ค.
enum Sex: String {
case male, female
}
typealias MyClass = [String: Sex]
var class1: MyClass = [:]
class1["๊น์ฒ ์"] = .male
class1["์ด์ํฌ"] = .female
class1["๋ฐํฅ์"] = .male
var class2: MyClass = [:]
class2["์ ์์"] = .female
class2["๊น์ง์"] = .female
class2["์ก์ํธ"] = .male
์์ ๊ฐ์ด Dictionaries ๋ฅผ ์ด์ฉํ ๋์ ํ์ ์ ์ฌ์ฉํ ์ ์์ผ๋, Classes ์ ๊ฐ์ ๊ฐ์ฒด๋ฅ ๋ฐ์ดํฐ๋ ์ ์ ํ์ ์ด๊ธฐ ๋๋ฌธ์ ๋ค์๊ณผ ๊ฐ์ด ๋์ ํ์ ์ properties ๋ฅผ ๋ง๋ค์ด ์ ์ฅํด์ผํ๋ค.
enum Sex: String {
case male, female
}
struct MyClass {
var student: [String: Sex] = [:]
}
var class1: MyClass = MyClass()
class1.student["๊น์ฒ ์"] = .male
class1.student["์ด์ํฌ"] = .female
class1.student["๋ฐํฅ์"] = .male
var class2: MyClass = MyClass()
class2.student["์ ์์"] = .female
class2.student["๊น์ง์"] = .female
class2.student["์ก์ํธ"] = .male
ํ์ง๋ง TypeScript ์ Classes ๋ ์ฌ์ค Object ๊ณ , ์ด๊ฒ์ ๋ง๋๋ ํจ์๋ฅผ ์ฌ์ฉํ๊ธฐ ์ฝ๊ฒ ๋ง๋ Syntactic Sugar ์ ๊ฐ๊น์ด Dynamic Type Language ์ด๊ธฐ ๋๋ฌธ์ String Index Signatures ๋ฅผ ์ฌ์ฉํด ๋ค์๊ณผ ๊ฐ์ด Classes ์ ๋์ ์ผ๋ก ์ ์ธํ๋ ๊ฒ์ด ๊ฐ๋ฅํ๋ค.
type Sex = 'male' | 'female';
class MyClass {
[index: string]: Sex;
}
const class1 = new MyClass();
class1['๊น์ฒ ์'] = 'male';
class1['์ด์ํฌ'] = 'female';
class1['๋ฐํฅ์'] = 'male';
const class2 = new MyClass();
class2['์ ์์'] = 'female';
class2['๊น์ง์'] = 'female';
class2['์ก๋ช
ํธ'] = 'male';
4. Inheritance
TypeScript ์ ์์ ์ญ์ Override ๋ฅผ ํตํด ๋ฉ์๋๋ฅผ ์์ ํจ์ ๋ฌผ๋ก , properties ์ Access Levels ๋ฅผ
๋ณ๊ฒฝํ๋ ๊ฒ ์ญ์ ๊ฐ๋ฅํ๋ค. ๋ํ, ๋ถ๋ชจ์ ์ ๊ทผํ ๋ super
ํค์๋๋ฅผ ์ฌ์ฉํ๋ ๊ฒ ์ญ์ ๋์ผํ๋ค.
class Vehicle {
protected currentSpeed = 0;
get description(): String {
return `traveling at ${this.currentSpeed} miles per hour`;
}
makeNoise() {
// do nothing - an arbitrary vehicle doesn't necessarily make a noise
}
}
class Car extends Vehicle {
override get description(): String {
return `${super.description} in gear ${this.gear}`;
}
constructor(
public gear: number = 1,
public override currentSpeed: number = 0
) {
super();
this.gear = gear;
this.currentSpeed = currentSpeed;
}
}
const myCar = new Car();
myCar.gear = 5;
myCar.currentSpeed = 10; // ์์์ ํตํด ์ ๊ทผ ๊ฐ๋ฅํ๋๋ก Access Level ์ ๋ณ๊ฒฝํ๋ค.
console.log(myCar.description); // "traveling at 10 miles per hour in gear 5"
5. Abstract Classes
Swift ์์๋ Protocols ์ Default Implementations ๋ฅผ ์ ๊ณตํ ์ ์๋ค. ๋ํ Java ์ญ์ Java 8 ๋ถํฐ Interfaces ์ Default Methods ๋ฅผ ๊ตฌํํ๋ ๊ฒ์ด ๊ฐ๋ฅํ๋ค.
๊ทธ๋ผ์๋ Abstract Classes
๊ฐ ์๋ฏธ๋ฅผ ๊ฐ๋ ๊ฒ์ Protocols ๋ Interfaces ๊ฐ ์๋ฏธ๋ฅผ ๊ฐ๋ ๊ฒ์ ๋ฉ์๋์
๋ํ ๊ธฐ๋ณธ ๊ตฌํ์ผ ๋ฟ, Instance Properties ๋ฅผ ๊ธฐ๋ณธ ๊ตฌํ์ผ๋ก ๊ฐ์ง ์ ์๋ ๊ฒ์ ์๋๊ธฐ ๋๋ฌธ์ด๋ค.
๊ทธ๋ฆฌ๊ณ ์ฐ๋ฆฌ์๊ฒ ๋์ฑ ์ค์ํ ๊ฒ์ TypeScript ์ Interfaces ๋ ๊ทธ ์ด๋ค
๊ธฐ๋ณธ ๊ตฌํ๋ ์ ๊ณตํ ์ ์๋ค๋ ๊ฒ ๋๋ฌธ์ด๋ค.
abstract class AbstractPerson {
protected _name: string = 'Mark';
abstract setName(name: string): void;
sayHello(): void {
console.log(`Hello, I'm ${this._name}.`);
}
}
interface IPerson {
_name: string;
setName(name: string): void;
}
7. Generics ๐ฉโ๐ป
1. Syntax
๋ค๋ฅธ ์ธ์ด์ ๋ง์ฐฌ๊ฐ์ง๋ก Generic Types ๋ฅผ ์ฌ์ฉํ ํจ์ ์ ์ธ์ ๋ค์๊ณผ ๊ฐ์ด ํ๋ค.
function hello<T>(message: T): T {
return message;
}
const hello = <T>(message: T): T => message;
๊ทธ๋ฐ๋ฐ ์ฌ์ฉํ ๋ ์ฃผ์ํด์ผํ ๊ฒ์ด ์๋ค.
hello('Hello World!');
๋ณดํต ๋ค๋ฅธ ์ธ์ด์์ ์์ ๊ฐ์ด ์ฌ์ฉํ๋ฉด ๋ฌธ์์ด๋ก ์ถ๋ก ๋๋ค. ํ์ง๋ง TypeScript ์์ ์ด๊ฒ์ 'Hello World!'
๋ผ๋
ํ์
์ผ๋ก ์ถ๋ก ํด๋ฒ๋ฆฐ๋ค!!
์ฆ, string
์ด ์๋ ๋ค์๊ณผ ๊ฐ์ substring
ํ์
์ด ๋๋ ๊ฒ์ด๋ค.
type HelloWorld = 'Hello World!';
๋ฌผ๋ก , ์ด๋ ๊ฒ ํ๋๋ผ๋ substring ์ญ์ string ์ ๋ฉ์๋๋ฅผ ์ฌ์ฉํ ์ ์๊ธฐ ๋๋ฌธ์ ํฐ ๋ฌธ์ ๋ ์๋ค. ํ์ง๋ง
์ด๊ฒ์ ํ์
์ด string ์ด ์๋ 'Hello World!'
๋ผ๋ substring ํ์
์ด๋ผ๋ ๊ฒ์ ์ธ์งํ๊ณ ์ฌ์ฉํด์ผํ๋ค.
๋ง์ฝ, string, number ์ ๊ฐ์ ์ผ๋ฐํ ๋ ํ์ ์ ์ฌ์ฉํ๋ ค๋ฉด ๋ฐ๋์ ์๋์ ๊ฐ์ด ํจ์๋ฅผ ํธ์ถํ ๋ ์ง์ ํ์ ์ ์ค์ ํด์ค์ผํ๋ค.
hello<string>('Hello World!');
hello<number>(123);
2. Generics Array & Tuple
Array
function helloarray<T>(arr: T[]): T {
return arr[0];
}
helloarray([1, 2, 3]);
helloarray(['a', 1, 'b', 2, 'c']);
์์์ ๋ณธ ๊ฒ์ฒ๋ผ ์ด ๊ฒฝ์ฐ ํ์
์ [1, 2, 3]
์ผ ๊ฒ ๊ฐ์ง๋ง Object ํ์
์์๋ ๋ค๋ฅธ ์ธ์ด์ ๋ง์ฐฌ๊ฐ์ง๋ก ๊ทธ๊ฒ์
ํ์
์ด ์ถ๋ฐ๋๋ค. ์ฆ,
number[] => number
(string | number)[] => string | number
ํ์ ์ผ๋ก ์ถ๋ก ๋๋ค.
Tuple
๋ฐ๋ฉด Tuple ์ Array ์ ๋ฌ๋ฆฌ ์ด๋ฏธ ์ ํด์ง ํ์ ์ด๊ธฐ ๋๋ฌธ์
function hellotuple<T, U>(tuple: [T, U]): T {
return tuple[0];
}
hellotuple([1, 2]);
hellotuple(['a', 1]);
์ ํ์ ์ ๊ฐ๊ฐ
[number, number] => number
[string, number] => string
ํ์ ์ผ๋ก ์ ํํ ์ถ๋ก ๋๋ค.
3. Generic Function Type Alias & Interface
์์์ Generic Functions ๋ฅผ ํจ์ Function Declaration ๊ณผ Function Expressions ์ผ๋ก ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ ๋ณด์๋ค. TypeScript ์ด๋ฏ๋ก ํจ์๊ฐ ์ด๋ค ๋ชจ์ต์ ์ทจํด์ผํ๋์ง๋ฅผ ํํํ ์ ์๋ค.
type HellloFunctionGeneric = <T>(message: T) => T;
interface HellloFunctionGeneric {
<T>(message: T): T;
}
4. keyof
keyof
๋ฅผ ์ฌ์ฉํ๋ฉด ๊ฐ์ฒด์ keys
๋ฅผ ์ถ์ถํ ์ ์๋ค.
const Hobbies = [
'Movie',
'Music',
'Reading',
'Cooking',
'Dancing',
'Swimming',
] as const;
type Hobby = (typeof Hobbies)[number];
const oneHobby: Hobby = 'Reading';
const myHobbies: Hobby[] = ['Movie', 'Music', 'Reading', 'Cooking'];
keyof
๋ฅผ ์ฌ์ฉํ๋ฉด Hobbies
๋ฐฐ์ด๋ก๋ถํฐ One of Hobbies ๋๋ Some of Hobbies ์ ๊ฐ์ ๋ฐฉ์์ผ๋ก
ํ์
์ ๋ง๋ค์ด ์ฌ์ฉํ ์ ์๋ค.
์์์ ๋ณด์๋ฏ์ด TypeScript ์์ keyof
๋ ํ์
์ ๋ค๋ฃจ๋ ๋ฐ ๋งค์ฐ ๊ฐ๋ ฅํ ๋๊ตฌ๋ก ์ฌ์ฉ๋๋ค. ๊ทธ๋ฆฌ๊ณ ์ด ํค์๋๋
Generics ์ ํจ๊ป ์ฌ์ฉํ๋ฉด ๋ ๊ฐ๋ ฅํ ๋๊ตฌ๊ฐ ๋๋ค.
interface IPerson {
name: string;
age: number;
}
const person: IPerson = {
name: 'John',
age: 36,
};
function getProp(obj: IPerson, key: keyof IPerson): IPerson[keyof IPerson] {
return obj[key];
}
keyof
๋ฅผ ์ฌ์ฉํด ํ๋์ฝ๋ฉ ์์ด ๋์ ์ผ๋ก ํ์
์ ์ค์ ํ์ง๋ง ๋ฐํ ํ์
์ด ์ฌ์ ํ
IPerson[โnameโ] | IPerson[โageโ] ๋ผ๋ Union Types ๋ฅผ ๋ฐํํ๋ ๋ฌธ์ ๊ฐ ์กด์ฌํ๋ค.
Generics ๋ฅผ ์ฌ์ฉํด๋ณด์.
function getProp<T>(obj: T, key: keyof T): T[keyof T] {
return obj[key];
}
const prop1 = getProp<IPerson>(person, 'name');
์ด์ IPerson[โnameโ] | IPerson[โageโ] ๋ณด๋ค๋ ํ์
์ด ์ข ๋ ์ ํํ๊ฒ ํํ๋์ง๋ง ์ฌ์ ํ
string | number
๋ผ๋ Union Types ๋ฅผ ๋ฐํํ๋ค. keyof T
๋ฅผ ํจ์๊ฐ ํธ์ถ๋ ๋ ํ์
์ด ์ ํ๋๋๋ก ํ๋ฉด ๋ฒ์๋ฅผ
๋ ์ขํ ์ ์์ ๊ฒ ๊ฐ๋ค.
T
๊ฐ ์ ํด์ง๋ฉด, ์ด T
๋ก๋ถํฐ ์ ํ๋ key
๋ฅผ ํ์
์ผ๋ก ๊ฐ๋๋ก ๋ ๋ฒ์งธ ๋ณ์ K
๋ฅผ ๋์
ํด๋ณด์.
function getProp<T, K extends keyof T>(obj: T, key: K): T[K] {
return obj[key];
}
const prop1: string = getProp(person, 'name');
const prop2: number = getProp(person, 'age');
ํจ์๊ฐ ํธ์ถ๋๋ ์๊ฐ ๊ฐ๊ฐ
function getProp<IPerson, "name">(obj: IPerson, key: "name"): string
function getProp<IPerson, "age">(obj: IPerson, key: "age"): number
์ ๊ฐ์ด ํ์ ์ด ๋ช ํํ ์ ์๋๊ธฐ ๋๋ฌธ์ ๋์ด์ Union Types ๋ฅผ ๋ฐํํ์ง ์๋๋ค.
์์ ๊ฐ์ ๋ฐฉ๋ฒ์ผ๋ก setProp
ํจ์๋ ์ ์ํ ์ ์๋ค.
function setProp<T, K extends keyof T>(obj: T, key: K, value: T[K]): void {
obj[key] = value;
}
Reference
- ์ด์ ์ฌ, โํ ๋ฒ์ ๋๋ด๋ React์ ๋ชจ๋ ๊ฒ ์ด๊ฒฉ์ฐจ ํจํค์ง, Part 6. TypeScript Essentialsโ fastcampus.co.kr. last modified unknown, Fast Campus.
- โConditional Types.โ typescriptlang.org. accessed Dec. 23, 2023, TypeScript - Conditional Types.
- โIntro to the TSConfig Reference.โ typescriptlang.org. accessed Dec. 24, 2023, TypeScript - TSConfig Reference.
- โCompile on save.โ GitHub. Dec. 24, 2023, https://github.com/TypeStrong/atom-typescript#compile-on-save.
- โtsconfig.json.โ TypeScript. access Dec. 24, 2023, [TypeScript - tsconfig].