프로필사진
TypeScript 문법 정리

2020. 1. 16. 17:50🔴 FE/TypeScript

300x250

참고 도서


TypeScripts는 JavaScript의 상위 집합,
따라서 JavaScript에서 제공하는 기능 외에 몇가지 기능을 추가했음

ES5의 모든 문법을 지원하고 ES6문법 대부분을 지원함


1. 타입지정

변수를 선언하면서 타입을 지정할 수 있음

let name1 = 'kang';
let name2 : string = 'kang';

타입을 지정하면 TypeScript 컴파일러가 컴파일할 때 잘못 사용된 코드를 잡아낼 수 있고, IDE에서도 자동완성 기능이나 리팩토리 기능을 제공할 수 있음 (생산성 upup!)

- 변수, 함수의 인자, 함수의 반환값에 타입을 지정할 수 있음
- 변수의 값은 JavaScript와 마찬가지로 null, undefined 가능
- 타입을 명시하지 않으면 값이 처음 할당될 때 모든 타입 허용 (any타입)

// 타입을 any로 지정하면 어떤 타입 값이라도 가능함
let name2 : any = 'kang';
name2 = 123;

1-1. 함수

인자와 반환값에 타입을 지정할 수 있음

function test (name : string, money : number) : number {
...
}

인자값의 타입을 지정해주면 잘못된 값이 들어왔을 경우 알 수 있음

// 반환값을 number로 지정했는데 string으로 하면 에러남
let result : string = test ('kang', 1);

1-2. 인자 기본값

함수를 선언하면서 함수의 인자가 전달되지 않을 떄 사용할 기본값을 지정할 수 있음
** 주의 : 기본값을 지정하는 인자는 마지막 인자부터 채워져야 함!!!

function test(name : string, money : number = '123') : number {
...
}

money의 기본값을 '123'으로 지정했기 때문에
let result : number = test('kang', 111); 또는 let result : number = test('kang'); 코드를 실행할 수 있음

1-3. 옵션 인자

생략할 수 있는 함수의 인자 이름 뒤에 물음표를 붙여서 옵션 인자로 지정
- 옵션인자도 함수를 선언할 때 마지막 인자부터 채워져야 함
- 옵션인자가 전달되지 않았을 때 처리할 로직도 만들어줘야 함

function test(name : string, money? : number) : number {
...
  if (money) {
  ..
  } else {
  .. 
  }
}

1-4. 화살표 함수 표현식

익명 함수를 간단하게 사용할 수 있는 문법 : function키워드를 사용하지 않아도 됨
ES6의 문법이며, 다른 언어에서는 람다 표현식이라고도 함

let getName = () => 'kang';
console.log(getName());

빈 괄호 = 함수에 전달되는 인자가 없다
함수의 몸체가 한줄 -> 중괄호, return 필요 없음

- JavaScript에서 문제되었던 this 키워드 문제를 해결하는 방법이기도 함
JavaScript에서 this -> 함수가 실행되는 컨텍스트 대신 다른 객체를 가리키는 경우가 있음 (런타임 버그)

function test2 (symbol : string) {
	this.symbol = symbol;
    
    setInterval(() => {
    	console.log('test2', this.symbol);
    }, 1000);
}

let result2 = new test2('kang');

1) 화살표 표현식을 사용하면 test2의 컨텍스트를 가리키는 변수가 따로 저장되어 있다가 함수 표현식 안에서 this를 참조할 때 가져와서 사용함 this.symbol = 'kang'

function test3 (symbol : string) {
	this.symbol = symbol;
    
    setInterval(function() {
    	console.log('test2', this.symbol);
    }, 1000);
}

let result3 = new test3('kang');

2) this가 가리키는 객체는 전역 window객체이기 때문에 this.symbol = undefined

정리 :

* Typescript코드를 Typescript컴파일러로 컴파일하면 JavaScript코드가 된다.
* Typescript에서는 변수나 함수의 인자,함수의 반환값에 타입을 지정할 수 있다.
* 함수를 선언할 때 인자의 기본값을 지정할 수 있고, 생략할 인자도 지정할 수 있다.
* 화살표 함수 표현식은 익명함수를 좀 더 간단하게 사용하기 위한 문법이다.
* 익명 함수에서 this객체를 사용할 때 가리키는 객체가 애매했던 문제는 화살표 함수 표현식에서 해결되었다.


2. 클래스

- Typescript에서는 클래스에 대한 정의를 메모리에 청사진처럼 만들어두고 인스턴스를 생성할 때마다 불러와서 사용함
- JavaScript와 달리 class, extends 키워드를 지원함 -> 하지만 JavaScript으로 변환하면 결국 프로토타입을 활용한 상속이 됨 (class를 활용하면 클로저를 사용할 때보다 더 간단하게 클래스를 정의할 수 있음!)

class Person {
	name : string;
    age : number;
}

var p = new Person();

p.name = 'Kang';
p.age = 1;

인스턴스를 생성할 때 생성자를 사용해서 프로퍼티를 초기활 할 수 있음
(이 생성자는 인스턴스가 생성될 때 한 번만 사용됨)

class Person {
	name : string;
    age : number;
    
    constructor( name : string, age : number) {
    this.name = name;
    this.age = age;
    }
}

var p = new Person('Kang', 1);

2-1. 접근 제한자

JavaScript : 클래스 변수나 메소드에 접근 범위를 지정하는 기능이 없음
TypeScript : public, protected, private (기본 : public)

class Person {
	public name : string;
    public age : number;
    private _ssn : string;
    
    constructor( name : string, age : number, ssn : string) {
    this.name = name;
    this.age = age;
    this._ssn = ssn;
    }
}

var p = new Person('Kang', 1, '1234');
console.log(p._ssn); // 클래스 밖에서 호출하고 있기 때문에 에러

private으로 지정하는 변수 -> '_' 붙여서 구분시킴

class Person {
   
    constructor( pubic name : string, public age : number, private _ssn : string) {
    }
    
}

var p = new Person('Kang', 1, '1234');​

생성자에서 접근제한자를 지정할 수 있음

2-2. 메소드

= 클래스 안에 선언된 함수 (일반 함수와 구별)

JavaScript : 메소드 선언하려면 객체의 프로토타입에 함수를 추가
TypeScript : 클래스 문법 사용 -> 객체 기반 언어에서 일반적으로 사용하는 문법으로 메소드 선언 가능

class testClass {

	doSomething (times : number) : void {
    ...
    }
}

let tc = new testClass();
tc.doSomething(11);

static doSomething() -> 정적 클래스 멤버로 만들면 인스턴스를 만들지 않아도 tc.doSometing(11);로 접근 가능

class Person {
   
    constructor( pubic name : string, public age : number, private _ssn? : string) {
    }
    
    get ssn() : string {
    	return this._ssn;
    }
    
    set ssn(value : string) : string {
    	return this._ssn = value;
    }
    
}

var p = new Person('Kang', 1);
p.ssn = '1234'; // setter 실행됨

getter, setter 메소드 생성 -> 클래스 인스턴스 만들고 _ssn값 설정함
** TypeScript에서는 클래스의 다른 멤버에 접근할 때 this키워드를 생략 할 수 없음

2-3. 상속

JavaScript : 프로토타입을 사용한 객체 기반 상속 지원
TypeScript : extends 키워드 사용해서 클래스 상속 할 수 있음

class Employee extends Person {
	location : string;
   
    constructor( name : string, age : number, _ssn : string, location : string) {
    	super(name, age, _ssn);
        this.location = location;
    }
}

Employee클래스 -> Person클래스 상속함
- 자식 생성자 정의 -> 부모 생성자 반드시 호출해야함 (this 또는 super[명시적 호출])

정리 :

* Angular는 ES5, ES6 버전의 JavaScript으로 작성할 수 있지만, TypeScript를 사용하는 것이 가장 효율적이다.
* TypeScript는 변수의 타입을 지정할 수 있으며, 기본 자료형은 물론이고 커스텀 타입도 사용할 수 있다. 이 타입 정보는 트렌스파일러가 코드를 변환할 때 모두 사라지기 때문에 브라우저에서 이 코드를 실행하는 데에 문제가 없다.
* .ts파일을 TypeScript컴파일러로 컴파일하면 .js파일이 만들어진다. 컴파일러는 파일의 변경을 감지하고 자동으로 컴파일하는 워치 모드로 동작할 수 있다.
* TypeScript에서 제공하는 클래스 문법을 사용하면 코드의 가독성을 높일 수 있다. TypeScript의 클래스와 상속 개념은 다른 객체 기반 언어와 동일하다.
* 클래스 멤버에 접근하는 권한을 제어하기 위해 접근 제한자를 사용할 수 있지만, Java나 C#처럼 엄격하지 않다.


3. 제네릭

https://github.com/Microsoft/TypeScript/blob/1344b14bd54854fd8d8993b625d9aca6368d1835/bin/lib.d.ts

 

microsoft/TypeScript

TypeScript is a superset of JavaScript that compiles to clean JavaScript output. - microsoft/TypeScript

github.com

>> 'interface array'검색해서 제네릭 활용 확인

함수를 정의할 때 인자의 타입을 신경쓰지 않지만, 실행되는 시점에는 명확한 타입을 지정해서 사용하고 싶을 때 제네릭 사용함
- 홑화살괄호 (< >) 로 정의

class Person {
	name : string;
}

class Employee extends Person {
	location : string;
}

class Animal {
	breed : string;
}

let workers : Array<Person> = [];
workers[0] = new Person();
workers[1] = new Employee();
workers[2] = new Animal(); // 에러!!

배열의 타입 = Person, 따라서 Animal은 넣을 수 없음 (컴파일 할 때 에러 발생)
모든 타입 허용시키려면 -> <any>로 변경해야함

functnion something<T> (data:T) {
}

something<string>('hi');
something<string>(111); // 에러!!

클래스나 함수에 제네릭을 사용할 수 있음
- 전달된 인자가 타입에 맞지 않으면 에러 발생
- 하지만 JavaScript으로 변환되는 코드에서는 제네릭에 대한 정보가 사라지기 때문에 JavaScript코드에서는 에러 발생 안함 (제네릭에 대한 에러는 컴파일 시점에만 발생함)


4. 인터페이스

JavaScript : 인터페이스 지원 안함
TypeScript : 자체적으로 인터페이스 기능 제공함 (interface, implements 키워드 사용) -> 개발 생산성 향상

4-1. 커스텀 타입으로 사용하기

인터페이스 내에 필수 항목으로 사용할 프로퍼티 선언 -> 함수에 전달하는 인자의 형식 고정
TypeScript 컴파일러가 인자의 유효성을 먼저 검사함

interface IPserson {
	name : string;
    age : number;
    ssn? : string;
}

class Person {
	constructor (public config : IPerson) {
    ... }
}

// IPerson 형태에 맞게 객체 생성 (객체 리터럴 문법)
let aPerson : IPerson = {
	name : 'Kang',
    age : 1,
}

let p = new Person(aPerson);
console.log(p.config.name);
let anEmployee : IPerson = {
	name : 'Kang',
    age : 11,
    location : 'Seoul'
};

IPerson에 정의되어 있는 name, age포함하고 있음 + 추가적으로 location도 정의 -- (가능)

4-2. 추상클래스로 사용하기

메소드 형태만 선언해서 인터페이스 정의, 이후엔 클래스 정의할 때 implements 키워드 사용하면서 인터페이스 지정 -> 추상함수로 선언된 메소드의 몸체를 모두 정의해야함

interface IPayable {
	increasePay (percent : number) : boolean
}

class Person {
...
}

class Employee extends Person implements IPayable {
	increasePay (percent : number) : boolean {
    ...
    }
}

Employee -> Person 클래스 상속받고 IPayable 인터페이스를 기반으로 정의함

4-3. 실행할 수 있는 인터페이스 (callable interface)

인터페이스의 메서드를 정의할 때 익명 함수 사용 -> 실행할 수 있는 인터페이스를 정의할 수 있음

interface IPayable {
	(percent : number) : boolean;
}

class Person {
	constructor (private validator : IPayable) {
    ... }
    
    increasePay (percent : number) : boolean {
    	return this.validator(percent);
    }
...
};

Person -> IPayable인터페이스를 인자로 받음
this.validator -> Person클래스 생성자에 인자로 전달된 IPayable인터페이스의 익명 함수를 가리킴

300x250