VSCode -> Open files -> 하단에 새로 만들기 -> 폴더명 입력 -> 더블클릭 -> 안에 text.ts파일 하나 만들기
npm init
npm install
타입스트립트를 global로 설치 (어디서나 실행가능하게끔)
npm i typescript -g
tsc는 TypeScript compiler의 약자. TypeScript compiler를 사용하겠다는 명령어.
test.ts는 파일명.
tsc는 TypeScript코드로 쓰여진 test.ts파일을 JavaScript파일로 변경해준다.
tsc test.ts
설정파일 생성 (tsconfig.json)
tsc --init
tsc
파일 수정됐을마다 새로 컴파일 시키기 (watch mode)
tsc -w
let a;
let a : string;
a = "Jenny";
혹은
let a = "Jenny"
이렇게 하면 a의 type은 바로 string으로 지정된다.
//JS
function add(n1, n2) {
if(typeof n1 !== 'number' || typeof n2 !== 'number) {
throw new Error('숫자만 입력해라잉')
}
return n1+n2
}
const result = add(39, 28)
//TS
function add(n1, n2) {
return n1+n2
}
const result = add(39, 28)
function hello1 (person : {name:string; age:number}) : void {
console.log('안녕! 나는 ${person.name}이야');
}
// 출력만 할꺼니까 return type은 void
const p1: {name:string; age:number} = {
name : "Jenny",
age: 26,
}
// p1은 Jenny, 26 값을 가진 객체
// 같은 구조를 가지고 있기 때문에 다음과 같이 hello1에 넣을 수 있다
hello1(p1);
근데 지금 {name:string; age:number}
가 중복이 되니, Person1이라는 데이터구조 (=interface)로 만들어 사용해보자.
interface Person1 {
name:string;
age:number;
}
function hello1 (person : Person1) : void {
console.log('안녕! 나는 ${person.name}이야');
}
const p1: Person1 = {
name : "Jenny",
age: 26,
}
interface Person3 {
name:string;
age?:number;
[index:string]:any;
}
const p32: Person3 = {
name = 'Anna',
sisters = ['Sung', 'Chan']
}
🍟 index가 sisters이고,
any니까 ['Sung', 'Chan']과 같은 배열도 가능, 객체도 가능, 모든 type 가능!!
Indexable type 형태는
[ ] : 어떤타입가능한지
객체 a 가 있다고 하면
a[index] 이렇게 들어오는건데 index자리엔 string만 허용.
그럼 예를 들어 a['Jenny'] 이렇게 들어온다는 것.
(JS에서 property 생성해서 넣어주는 원리와 동일)
즉,
a['Jenny']
의미와 같은 게 [index:string]
이라고 볼 수 있다.
근데 a['whatever']처럼 property의 실제 값은 아무거나 가능하므로 뒤에 :any
를 붙여주는 것.
사용한다기보다는 interface에 있는 내용을 바탕으로 Person이라는 class를 만들어 내는 것이다.
implements 사용
interface IPerson1 {
name: string;
age?: number;
hello(): void;
}
class Person implements IPerson1 {
}
이런 식으로 있으면,
Person 의 빨간밑줄 클릭하면 다음과 같이 자동완성된다.
class Person implements IPerson1 {
name: string;
age?: number | undefined;
hello(): void {
throw new Error("Method not implemented.");
}
}
그럼 이제 name에 빨간밑줄이 뜬다.
Property 'name' has no initializer and is not definitely assigned in the constructor.
Why?
name의 초기값이 지정되어있지 않다는 의미.
constructor 사용
class Person implements IPerson1 {
name: string;
age?: number | undefined;
constructor(name : string) {
this.name = name;
}
hello(): void {
throw new Error("Method not implemented.");
}
}
const person = new Person("Jenny")
person에 마우스를 갖다 대면, Person이라는 class type으로 지정이 되어있는 걸 볼 수 있다.
근데IPerson1
이라는 interface로부터 구현(implements)됐기 때문에,
const person : IPerson1 = new Person("Jenny")
이렇게 쓸 수도 있다.
const person = new Person("Jenny")
person. 다음에 name, age?, hello를 쓸 수 있도록 뜸 (interface에 있는 내용임)
즉, 이 interface로부터 구현된 아이는
name: string; age?: number; hello(): void;
를 만족해야 한다.
이걸 만족하는 class를 만들어서 사용가능.
그 class는 class 이름으로 type을 부를 수 있지만, interface이름(IPerson1) 으로 부르는 게 더 정확한 표현이다.
person.hello();
이렇게 함수를 실행할 수 있다.
이제는, 외부로는 interface만 노출하고, 내부적으로는 class 내부 구현하는 방식으로 작업하게 된다.
interface 끼리 상속하기
interface IPerson2 {
name: string;
age?: number;
}
interface IKorean extends IPerson2 {
city: string;
}
// 작은부분 extends 큰부분
// IKorean이 IPerson2의 형태를 상속한다.
// 그래서 IKorean 형태는 이렇게 된다:
name: string;
age?: number;
city: string;
const k : IKorean = {
name : "Jenny",
city: "Seoul",
}
// k는 객체
// "IKorean의 type형태를 가진다"라는 뜻이다.
함수를 interface로 만들어내기 (타이핑하기)
interface HelloPerson {
(name: string, age?: number) : void;
}
// return type은 void
const helloPerson : HelloPerson = function(name:string){
// helloPerson이라는 함수는 HelloPerson이라는 타이핑을 할거다.
console.log(`안녕. 나는 ${name}이야.`)
//helloPerson은 HelloPerson형태와 같아야 한다.
🍟 helloPerson은 뒤에 function보다는, HelloPerson와 더 연관성이 크다! 형태 동일해야.
//실행
helloPerson('Jenny')
helloPerson('Jenny', 26)
//function에 age부분 안써도 이렇게 실행가능.
//이 말은 즉슨, helloPerson함수에겐 HelloPerson interface의 형태가 가장 중요+영향력.
}