mkdir
: make directory : 폴더 생성
code .
: vscode 켜기
npm init -y
: 프로젝트 초기 설정을 하겠다. package.json 깔림
npm install typescript
: 해당 프로젝트에서만 타입스크립트 설치
npm -g install typescript
: 타입스크립트 전역적으로 설치
npx
: 사용할 모듈을 로컬에 저장하지 않고 매번 최신 버전의 파일을 불러와 사용한 다음 파일을 다시 없애는 방식
tsc
: tsc 타입스크립트 컴파일러
npx tsc -init
: tsc 타입스크립트 컴파일러를 해당 파일 혹은 전역에 저장하지 않고 그냥 한번 가져와서 쓰고 버리겠다. tsconfig.json 깔림
touch filename
: 파일 만들기 (Ex: touch hello.ts)
npm install -g ts-node
: 타스를 자스로 변환해서 출력할 수 있게 해주는 라이브러리 설치
ts-node ./filename
: ts파일 출력 (Ex: ts-node ./example)
가장 중요한 두 가지 target & module
target : 타입스크립트를 여기에 입력된 버전의 자바스크립트로 번역하겠다. (ES2016, ES2015)
module : 타스 > 자스 로 전환되는 과정에서 import 문법 정하는 곳 (commonjs, ES2015, ESNext 등)
브라우저는 타스를 이해하지 못하기 때문.
브라우저가 이해하는 것 : html, css, js
string / number / boolean /
array / tuple /
any / void / null / undefined / never
// String
let str: string = 'Typescript';
let fullName: string = 'Kelly';
let sentence: string = `my name is ${fullName}.`;
// Number
// 2진수, 8진수, 10진수, 16진수 지원
let binary: number = 0b1010; // 2진수, 0b-
let octal: number = 0o744; // 8진수, 0o-
let decimal: number = 6; //10진수
let hex: number = 0xf00d; // 16진수, 0x-
// Boolean
let isTrue: boolean = true;
let isFalse: boolean = false;
// Array
let strArr: string[] = ['1', '2', '3'];
let strArr2: Array<string> = ['1', '2', '3'];
let numArr: number[] = [1, 2, 3];
let numArr2: Array<number> = [1, 2, 3];
let boolArr: boolean[] = [true, false, true];
let boolArr2: Array<boolean> = [true, false, true];
// Tuple
// ~개의 요소로 된 집합, 요소의 타입과 갯수가 고정된 배열
let x: [string, number];
x = [1, 'hi']; // 에러
x = ['hi', 1];
console.log(x[0], x[1]); // hi 1
x[2] = 'world'; // 에러, 정해진 배열의 길이를 뛰어넘음
let tuple: [string, number, boolean] = ['str', 1, false];
// Any
// 어떤 타입을 가진 값이든 다 들어갈 수 있는 것, 자스랑 비슷함
let string: any = 'hi';
string = 13;
string = 'abc';
string = true;
string = {};
// Void
// 함수 내에 리턴값이 없을 경우 반환값없음을 알려주는 용도의 타입, 변수 타입으로는 사용 안함
function d(): void {
console.log('d');
}
// null, undefined
// 변수에 할당할 값이 null, undefined 뿐이라 주로 unionType 활용시 많이 쓰임
let e: null = null;
let f: undefined = undefined;
let unionType: number | null = 123; // number 와 null 둘 다 할당 가능
// Never
// 함수가 끝까지 실행되지 않거나 함수가 비정상적으로 종료되었음을 의미
function g(): never {
while (true) {} // 실행 멈춤
}
function h(): naver {
throw new Error('Error'); // 에러발생으로 비정상적으로 종료
}
기본 / 리턴값 타입 생략 / 화살표 함수 / 반환값이 없는 함수 /
Optional Parameter / Default Parameter / Rest Parameter
// 기본
function add(n1: number, n2: number): number {
return n1 + n2;
}
// 반환값의 타입은 추론이 가능해서 생략한 함수
function add2(n1: number, n2: number) {
return n1 + n2;
}
// 화살표 함수
const add3 = (n1: number, n2: number) => {
return n1 + n2;
};
// 반환값이 없는 함수
function printResult(num: number): void {
console.log('Result' + num);
}
// Optional Parameter
// 조건문 함수와 '?'(:또는)붙여서 만드는 옵셔널 파라미터
// optional parameter에 아무 값이 할당되지 않았을 때, undefined 됨
// optional parameter는 required parameter 앞에 위치할 수 없음
function add4(n1: number, n2?: number) {
if (!n2) return n1;
return n1 + n2;
}
const a2 = add4(1, 2);
const b2 = add4(10, 20, 30); // 에러
const c2 = add4(10); // n2? 일때만 에러 안남
// Default Parameter
// 자스의 기능, default parameter에 아무 값이 할당되지 않았을 때, 설정해둔 값이 됨
function add5(n1: number, n2: number = 2) {
return n1 + n2;
}
const f2 = add5(10); // 2번째 파라미터가 없어서 n2값이 2로 초기화됨
console.log(f2); // 12
// Rest Parameter
// 자스의 기능, 나머지의 역할을 하는 파라미터
// 남는 파라미터들을 배열로 만들어줌
// 처음이나 중간에는 올 수 없고, 함수 파라미터의 마지막에만 올 수 있음
function add6(n1: number, ...nums: number[]) {
let totalOfNums = 0;
for (let key in nums) {
totalOfNums += nums[key];
}
return n1 + totalOfNums;
}
const result = add6(10, 20, 30, 40); //nums = [20,30,40]
console.log(result); // 100
숫자형 / 문자형 / 복합형
// 이넘 enum 타입
// 키 값으로 밸류를 불러올 수 있음 (.key 혹은 ['key'])
// 숫자형 이넘
// 인덱스처럼 다음순서로 가면 +1 씩 증가하는 순서 숫자를 가지고 있고,
// 안의 멤버 중 하나의 값을 수동으로 바꿔줄 수 있음
enum Direction {
Up,
Down = 100,
Left,
Right,
}
console.log(Direction.Up, Direction.Down, Direction.Left); // 0 100 101
const up: Direction = Direction.Up;
console.log(up); // 0
const leftOrRight: Direction.Left | Direction.Right = Direction.Left;
console.log(leftOrRight); // 101
console.log(Direction[100]); // Down
const ex1 = Direction['Down']; // 100
const ex2 = Direction.Down; // 100
// 문자형 이넘
// 이넘값 전부 특정 문자 또는 다른 이넘 멤버의 값으로 초기화 해야함
// 숫자형 이넘과 다르게 +1 씩 증가하는 것이 없음
enum Direction2 {
Up = 'Up',
Down = 'Down',
Left = 'Left',
Right = 'Right',
}
enum Language {
Korean = 'ko',
English = 'en',
Japanese = 'jp',
}
const ex3 = Language['Korean']; // "ko"
const ex4 = Language.Korean; // "ko"
// 복합형 이넘 (권고하지 않음)
// 숫자형 이넘과 문자형 이넘을 혼용사용하나 유지보수에 혼란줄 수 있음
enum BooleanLikeHeterogeneousEnum {
No = 0,
Yes = 'Yes',
}
// 유니온 타입 문법 (A || B)
// or 연산자와 마찬가지의 의미 (~이거나)
// | : 파이프 연산자
const printOut = (input: string | number) => {
console.log(input);
}; // 문자열타입 혹은 숫자타입을 input 에 할당할 수 있음
// 유니온 타입의 장점
// 다른 타입을 혼용해서 쓰고자 할 때 유용하다
function getAge(age: number | string) {
if (typeof age === 'number') {
age.toFixed(); // 숫자 관련 메서드
return age;
}
if (typeof age === 'string') {
return age;
}
}
function padLeft(value: string, padding: string | number) {
if (typeof padding === 'number') {
return Array(padding + 1).join(' ') + value;
}
if (typeof padding === 'string') {
return padding + value;
}
throw new Error(`Expected string or number, got'${padding}.`);
}
console.log(padLeft('Hello World', 4)); // " Hello World"
console.log(padLeft('Hello World', '!!!')); // "!!!Hello World"
console.log(padLeft('Hello World', true)); // 에러
// 기존에는 새로운 값이 생길 때마다 하나하나 다 넣어줘야 하는점이 불편했음
const hero: { name: string; power: number; height: number } = {
name: '슈퍼맨',
power: 1000,
height: 190,
};
const printHero = (hero: { name: string; power: number; height: number }) => {
console.log(hero.name, hero.power);
};
printHero(hero);
// 타입별칭을 만들어 놓으면, 타입 속 내용만 수정하면 자동으로 연결된 부분 에러를 찾아줌
// 현업에서는 타입을 따로 적은 파일을 밖으로 분리하고 import 해오는 식으로 사용
type Hero = {
name: string;
power: number;
height: number;
gender: '남' | '여';
};
const hero1: Hero = {
name: '슈퍼맨',
power: 1000,
height: 190,
gender: '남',
};
const printHero1 = (hero: Hero) => {
console.log(hero.name, hero.power);
};
// 인터페이스 interface
// 다른 언어에서 인테페이스는 class 구현 전 필요한 메서드를 정의하기 위해 쓰임
// 타스에서는 더 다양한 것들을 정리
// 인터페이스로 타입 정의하는 방법
// 기본 정의
interface Person1 {
name1: string;
age1: number;
}
const person1: Person = { name1: 'js', age1: 20 };
const person11: Person = { name1: 'js', age1: 'twenty' }; // 에러
// 선택속성
// 함수타입에서 배운 옵셔널 파라미터와 유사
interface Person2 {
name2: string;
age2?: number;
}
const person2: Person2 = { name2: 'js' };
console.log(person2.name);
// Read Only 속성
// 인터페이스로 객체를 처음 생성할때만 값을 할당 가능
// 그 이후에는 변경이 불가능한 속성
interface Person3 {
readonly name3: string;
age3?: number;
}
const person3: Person3 = { name3: 'js' };
person3.name3 = 'lij'; // 에러
let readonlyArr: ReadonlyArray<number> = [1, 2, 3];
readonlyArr.push(4); // 에러
readonlyArr[0] = 100; // 에러
// 인덱스 index 타입
// 인터페이스에서 속성의 이름을 구체적으로 정의하지 않고, 어떤 값의 타입만 정의하는 것
interface Person4 {
readonly name4: string;
[key: string]: number | string;
// 인덱스 key 에 어떤 string 이든 들어올 수 있고,
// value 에는 string 또는 number가 들어올 수 있다.
// key는 무조건 string, number만 들어올 수 있음
}
const p1: Person4 = { name4: 'js', birthDay: '비밀', age: 20 };
// 함수 타입
interface Print {
(name: string, age: number): string;
}
// type Print = (name: string; age: number) => string; 과 동일
const getNameAndAge: Print = function (name5, age5) {
return `name: ${name5}, age:${age5}`;
};
// 인터페이스 확장
interface Person {
name: string;
age: number;
}
interface Korean extends Person {
birth: 'KDR';
}
interface Korean {
name: string;
age: number;
birth: 'KDR';
}
interface Developer {
job: 'developer';
}
interface KorAndDev extends Korean, Developer {}
interface KorAndDev {
name: string;
age: number;
birth: 'KDR';
job: 'developer';
}
// intersection Type
// & 여러 타입을 모두 만족하는 하나의 타입
interface Person {
name: string;
age: number;
}
interface Developer {
name: string;
skill: string;
}
type DevJob = Person & Developer;
const nbcPerson: DevJob = {
name: 'a',
age: 20,
skill: 'ts',
};
인터페이스는 확장이 가능하고, 타입은 확장이 불가능하다.
때문에 type보다 interface를 선언해 사용하는 것을 추천
// 타입을 마치 함수의 파라미터처럼 사용하는 것
// 여러타입이 나올 수 있는 공통함수에서 많이 쓰임
function getText<T>(text: T): T {
return text;
}
getText<string>('hi');
getText('hi'); // 생략 가능(명시적 역할)
getText<number>(10);
getText<boolean>(true);
function getItemArray<T>(arr: T[], index: number): T {
return arr[index];
}
function pushItemArray<T>(arr: T[], item: T): void {
arr.push(item);
}
const techStack = ['js', 'react'];
getItemArray(techStack, 0); // 'js'
pushItemArray(techStack, 'ts'); // ['js', 'react', 'ts']
// 제네릭 타입 변수
function printedOut<T>(input: T[]): T[] {
console.log(input.length);
return input;
}
printedOut([1, 2, 3]);
// 제네릭 제약 조건
interface LengthMise {
length: number;
}
function printedIn<T extends LengthMise>(input: T): T {
console.log(input.length);
return input;
}
printedIn(10); // 에러
printedIn({ length: 0, value: 'hi' });
타입을 넣어주지 않아도 자동으로 각 타입을 인식하는 것
// let 으로 선언된 변수는 재할당이 가능해 융통성있게 타입이 결정되는데,
let a = 123;
let b = 'abc ';
a = 'abc'; // 에러
b = 123; // 에러
// const 로 선언된 변수는 재할당이 불가능해 엄격하게 타입이 결정됨.
const c1 = 123; // c1의 타입은 123
c1 = 124; // 에러
// Array
const arr = [1, 2, 3];
const [n1, n2, n3] = arr; // n1, n2, n3의 타입을 number임
arr.push['a']; // 에러
// Object
const obj = { numId: 1, stringId: '1' };
const { numId, stringId } = obj;
console.log(numId === stringId); //에러(비교불가, 자료형 다르니까)
// Function
// 같은 매개변수 자리에 다른 타입을 허용할 때
const func1 = (a: number | string = 'a', b = 1) => {
return `${a}+${b}`;
};
func1(3, 6);