Woongjae Lee
NHN Dooray - Frontend Team
type alias
// Basic Types Example
type A = string;
const a: A = '스트링';
// Custom Types Example
interface Person {
name: string;
}
type B = Person;
const b: B = {
name: 'mark'
};
type alias & keyof keyword
// Basic Types Example
type A = keyof string;
const a: A = 'toString'; // string 의 프로퍼티 이름들만 값으로 올수 있는 타입
// Custom Types Example
interface Person {
name: string;
age: number;
}
type B = keyof Person;
const b: B = 'name'; // Person 의 프로퍼티 이름 중 하나
Lookup Type System (1) - before
interface Person {
name: string;
age: number;
}
function getProperty(obj, key) {
return obj[key];
}
function setProperty(obj, key, value) {
obj[key] = value;
}
const person: Person = {
name: 'mark',
age: 35
};
const personName: boolean = getProperty(person, 'name');
setProperty(person, 'age', 'mark');
Lookup Type System (2) - after
interface Person {
name: string;
age: number;
}
function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
return obj[key];
}
function setProperty<T, K extends keyof T>(obj: T, key: K, value: T[K]): void {
obj[key] = value;
}
const person: Person = {
name: 'mark',
age: 35
};
const test: boolean = getProperty(person, 'name');
setProperty(person, 'age', 'mark');
// error TS2322: Type 'string' is not assignable to type 'boolean'.
// error TS2345: Argument of type '"mark"' is not assignable to parameter of type 'number'.
Partial<T>
interface Person {
name: string;
age: number;
}
// duplicate
// 이미 구현되어 있습니다.
/*
type Partial<T> = {
[P in keyof T]?: T[P];
};
*/
type PartialPerson = Partial<Person>;
Readonly<T>
interface Person {
name: string;
age: number;
}
// duplicate
// 이미 구현되어 있습니다.
/*
type Readonly<T> = {
readonly [P in keyof T]: T[P];
};
*/
type ReadonlyPerson = Readonly<Person>;
Deffered<T>
interface Person {
name: string;
age: number;
}
// 구현되어 있지 않습니다.
type Deferred<T> = {
[P in keyof T]: Promise<T[P]>;
};
type DeferredPerson = Deferred<Person>;
Pick<T, K>
declare function pick<T, K extends keyof T>(obj: T, ...keys: K[]): Pick<T, K>;
interface Person {
name: string;
age: number;
}
const mark = {
name: 'mark',
age: 35
};
const onlyNameMark = pick(mark, 'age');
Object Spread & Rest
// shallow copy example
const original = {
a: 'a',
b: 'b',
c: 'c'
};
// const copied = original;
const copied = {...original};
// 합체
const sub1 = {x: 'x', y: 'y'};
const sub2 = {z: 'z'};
const merged = {...sub1, ...sub2};
// 추출
// const {a, obj} = original; // obj = {b: 'b', c: 'c'}
const {a, ...obj} = original; // obj = {b: 'b', c: 'c'}
compile option
{
"compilerOptions": {
"target": "es5",
"lib": ["dom", "es2015.promise", "es5"]
}
}
소스 코드 (.ts)
class Parent {
}
class Child extends Parent {
}
compile 결과 (.js) - before
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
exports.__esModule = true;
var Parent = (function () {
function Parent() {
}
return Parent;
}());
var Child = (function (_super) {
__extends(Child, _super);
function Child() {
return _super !== null && _super.apply(this, arguments) || this;
}
return Child;
}(Parent));
exports.Child = Child;
compile 결과 (.js) - after
"use strict";
exports.__esModule = true;
var tslib_1 = require("tslib");
var Parent = (function () {
function Parent() {
}
return Parent;
}());
var Child = (function (_super) {
tslib_1.__extends(Child, _super);
function Child() {
return _super !== null && _super.apply(this, arguments) || this;
}
return Child;
}(Parent));
exports.Child = Child;
any example
let x;
// You can still assign anything you want to 'x'.
x = () => 42;
// After that last assignment, TypeScript 2.1 knows that 'x' has type '() => number'.
let y = x();
// Thanks to that, it will now tell you that you can't add a number to a function!
console.log(x + y);
// ~~~~~
// Error! Operator '+' cannot be applied to types '() => number' and 'number'.
// TypeScript still allows you to assign anything you want to 'x'.
x = "Hello world!";
// But now it also knows that 'x' is a 'string'!
x.toLowerCase();
literal => const / let
const c1 = 1; // Type 1
const c2 = c1; // Type 1
const c3 = "abc"; // Type "abc"
const c4 = true; // Type true
const c5 = cond ? 1 : "abc"; // Type 1 | "abc"
let v1 = 1; // Type number
let v2 = c2; // Type number
let v3 = c3; // Type string
let v4 = c4; // Type boolean
let v5 = c5; // Type number | string
피쳐 내용
class Base {
x: number;
constructor() {
// return a new object other than `this`
return {
x: 1,
};
}
}
class Derived extends Base {
constructor() {
super();
this.x = 2;
}
}
기존 방식
class CustomElement {
private _element: HTMLElement;
constructor() {
this._element = document.createElement('div');
}
...
}
새로운 방식
class CustomElement extends HTMLElement {
constructor() {
super();
}
}
const e = new CustomElement();
document.body.addChild(e);
es5 돌아가는 코드
class TestElementMaker extends HTMLElement {
constructor() {
super();
}
public test(): void {
console.log('테스트');
}
}
const TestElement = document.registerElement("test-element", TestElementMaker);
const e = new TestElement();
e.test();
configs/base.json
{
"compilerOptions": {
"noImplicitAny": true,
"strictNullChecks": true
}
}
tsconfig.json
{
"extends": "./configs/base",
"files": [
"main.ts",
"supplemental.ts"
]
}
tsconfig.nostrictnull.json
{
"extends": "./tsconfig",
"compilerOptions": {
"strictNullChecks": false
}
}
By Woongjae Lee
타입스크립트 한국 유저 그룹 기술 세미나 201704