2020. 1. 16. 17:50ㆍ🔴 FE/TypeScript
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
>> '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인터페이스의 익명 함수를 가리킴
'🔴 FE > TypeScript' 카테고리의 다른 글
TypeScript & Angular 개발단계 (0) | 2020.01.17 |
---|---|
Angular에서 JavaScript대신 TypeScript사용하는 이유? (0) | 2020.01.16 |