- Typescript : Javascript에 Type을 추가해 기존 JS의 결핍을 채워주는 JS로 Compile되는 언어. Type을 검사하는 정적 타입 검사기이자 컴파일의 결과가 JS로 컴파일되는 언어로 .ts 확장자 사용
- MS가 개발해 2012년 0.8버전을 오픈소스로 공개. 2023년 현재 대부분의 text-editor에서 지원하며, 수많은 JS 관련 프로그램들이 TS를 기반으로 작성되고 있음.
1. 이점
1) Compile 시점에 에러 확인 가능
2) 개발 툴에서 개발자에게 상대적으로 더 많은 도움을 줄 수 있음. ex) 코드 자동완성 기능
function add(a, b) {
return a + b;
}
add(1, 2) // 3을 반환
add("1", "2") // 12를 반환
---------------------------------------------------------
function add(a: number, b: number) {
return a + b;
}
add(1, 2) // 3을 반환
add("1", "2") // 컴파일 에러
2. Playground에서 실행하기
- Typescript 공식 웹사이트에서 TS 작성 및 실행을 할 수 있는 환경 제공
https://www.typescriptlang.org/play
3. Node Runtime에서 실행하기
$ npm install -g typescript
$ tsc --version
$ cd project-dir
$ tsc --init
// hello-ts.ts
const message = "Hello world";
console.log(message);
-------------------------------------------------------
// hello.ts.js 자동으로 생성됨
var message = "Hello world";
console.log(message);
-------------------------------------------------------
$ node hello-ts.js
4. ts-node로 실행하기
- Compile 과정 없이 바로 실행하기 위해 ts-node 패키지 설치
$ npm install -g ts-node
$ ts-node hello-ts.ts
1. 변수 선언
- 방법 : var, let, const
function foo( ) {
if (true) {
var a = 10;
}
return a;
}
console.log(foo( ));
// 결과
// 10
** if문 블록 안 변수 a를 블록 밖에서 리턴했음에도 불구하고 결과가 콘솔에 출력됨
** var는 함수 영역 내 어디서든 접근할 수 있음
** 이러한 이유로 최근에는 let과 const를 주로 사용함
function bar( ) {
if (true) {
let a = 10;
}
return a;
}
console.log(bar()); // 변수 a가 없는 에러 발생
** let은 block scope로 동작
** let은 변수값을 변경할 수 있고, const는 변경할 수 없음
let a = 10;
a += 1;
console.log(a); // 11출력
const b = 10;
b +=1;
console.log(b) // 에러 출력
** const에 값을 재할당 할 수 없다고 해서 불변은 아님. 할당한 변수에서 변경할 수 없는 것은 해당 변수의 메모리 주소 값(레퍼런스) 이며, const에 배열이나 객체 등을 할당하면 값을 변경할 수 있음.
2. Type annotation : type을 명시하는 법
let username: string = "Hoon"; // 문자열
let height: number = 175; // 숫자
let isConditionGood: boolean = true; // Boolean
// 함수의 매개변수와 결과값에 타입을 선언하는 법
function printMessage(message: string): void {
console.log(message);
}
// 객체에 타입을 선언하는 법
let myInfo : {name: string; height: number; isConditionGood: boolean } =
{ name: "Hoon",
height: 175,
isConditionGood: true,
};
// 선택적 속성 optional property
let myInfoWithGender: {
name: string;
height: number;
isConditionGood: boolean;
gender?: string; // 선택적 속성
} = {
name: "Hoon",
height: 175,
isConditionGood: true,
};
// 함수의 매개변수의 선택적 속성
function printMessageWithAlert(message: string, isCritical?: boolean): void {
console.log(message);
if (isCritical) {
alert(message);
}
}
3. 기본 Type 7종
- type(자료형)은 변수가 어떤 형식의 값을 갖는지 나타냄
1) null : 의도적으로 값이 없음을 나타낼 때 사용
2) undefined : 변수에 값이 할당도지 않은 경우, 즉 의도하지 않은 값의 부재 의미
3) boolean : true or false
4) string : 문자열
5) number : 정수, 부동소수점, 16진수, 8진수 등 숫자
6) bigint : 매우 큰 숫자 할당 가능한 타입. 숫자 뒤에 n을 붙여서 표시
7) symbol : 불변이면서 유니크한 값을 표현
const one: number = 1; // number
const myName: string = "Hoon"; // string
const trueOrFalse: boolean = true; // boolean
const unIntended: undefined = undefined; // undefined
const nullable: null = null; // null
const bigNumber: bigint = 1234567890123456789012345678901234567890n; // bigint
const symbolValue: symbol = Symbol("symbol"); // symbol
console.log(one + 1); // 2
console.log(myName + " is my name"); // Hoon is my name
console.log(trueOrFalse ? "true" : "false"); // true
console.log(bigNumber / 10000000000000000n); // 123456789012345678901234n
// 모든 값이 유일하므로 같은 값을 넣어도 false
console.log(symbolValue === Symbol("symbol"));
4. 배열과 튜플 Array & Tuple
- 데이터를 여러 개를 넣는다는 점에서 배열과 튜플은 유사하나, 배열은 크기가 고정이 아니고 튜플은 고정.
- 배열은 각 원소의 타입을 정의하고, 튜플은 원소 개수 만큼 타입을 정의해야 함
const numbers: number[] = [1, 2, 3, 4, 5]; // 숫자 배열
const stringArray: Array<string> = ["a", "b", "c", "d", "e"] // 문자열 원소
// 스프레드 연산자로 합치기 가능
const oneToTen = [...numbers, ...numbers2];
console.log(...oneToTen);
// 객체의 배열 타입
const idols: { name: string; birth: number}[ ] = [
{ name: "minji", birth: 2004 },
{ name: "hani", birth: 2004 },
{ name: "haerin", birth: 2006 },
];
// 배열의 원소가 객체인 타입
const gameConsoleArray: Array<{ name: string; launch: number }> = [
{ name: "PS5", launch: 2020 ],
{ name: "Nintendo Switch", launch: 2017 },
];
// 튜플은 원소 개수만큼 타입 정의 필요
const myTuple: [string, number] = ["Hoon", 175];
// 튜플은 함수의 매개변수가 여러개일 때 유용
function printMyInfo(label: string, info: [string, number]): void {
console.log(`[${label}]`, ...info);
}
// 결과값 : [튜플 테스트] Hoon 175
printMyInfo("튜플 테스트", myTuple);
// 튜플을 반환하는 함수
function fetchUser(): [string, number] {
return ["Hoon', 175];
}
// 결과값을 분해해서 받을 수 있음
const [name24, height24] = fetchUser( );
console.log(name24, height24);
5. any, void, never
let anyValue = 10; // number 타입으로 추론
anyValue = "hello"; // 컴파일 에러
anyValue = true; // 컴파일 에러
-------------------------------------------------------
let anyValue: any = 10;
anyValue = "hello";
anyValue = true;
**any type : 타입을 모르거나 지정할 수 없을 때 컴파일 에러를 피하기 위해 사용 가능
// 결과값이 없음
function print(value: any): void {
console.log(value);
}
// 예외를 던짐
function throwError(message: string): never {
throw new Error(message);
}
// 무한 루프
function infiniteLoop(): never {
while (true) {}
}
** void/never : 함수의 반환값에 지정하는 타입. void는 함수의 결과값이 없을 때 사용, never는 의도적으로 값을 반환하지 않는 때 사용. 예외를 발생시키는 함수이거나 무한루프를 실행하는 함수가 이에 해당됨.
6. union, narrowing
let anyValue: number | string | boolean = 10; //이 시점에서는 number
anyValue = "hello"; // string
anyValue = true; // boolean
** union type은 변수 하나에 두 개 이상의 타입을 지정하는 것으로 "|" 기호로 타입을 구분.
let anyValue: number | string | boolean = 10;
printAny(anyValue);
anyValue = "hello";
printAny(anyValue);
anyValue = true;
printAny(anyValue);
// 매개변수로 number, string, boolean을 할당할 수 있음
function printAny(value: number | string | boolean): void {
if (typeof value === "number") {
console.log(value.toExponential(3));
} else if (typeof value === "string") {
console.log(value.toUpperCase());
} else if (typeof value === "boolean") {
console.log(value ? "참" : "거짓");
}
}
** Narrowing은 말 그대로 타입의 범위를 좁히는 것. type guard(typeof, instanceof, in 등)를 사용해 값 할당 또는 조건문으로 검사해 타입을 좁힘.
7. Type 별칭
- 자주 재사용하는 유니온 타입의 경우 타입 별칭을 사용하면 편리. 타입 별칭은 type 키워드를 사용해 정의
type nsb = number | string | boolean;
- 이미 만든 타입에 추가로 타입을 넣어더 다시 별칭을 만드는 것도 가능
type nullableNsb = nsb | null | undefined
// 타입 별칭
type nsb = number | string | boolean;
let anyValue: nsb = 10;
anyValue = "hello";
anyValue = true;
anyValue = null; // 컴파일 에러
// 타입 별칭에 null, undefined 추가
type nullableNsb = nsb | null;
let nullableValue: nullableNsb = null;
nullableValue = 20;
nallableValue = "nullable";
nullableValue = false;
nullableValue = undefined; // 컴파일 에러
8. Intersection type
- A이면서 B인 타입을 정의. 기호도 "&"로 사용
type 타입명 = {
속성명: 타입;
}
type cup = {
size: string;
};
type brand = {
brandName: string;
};
type brandedCup = cup & brand; // cup이면서 brand가 있는 타입
let starbucksGrandeSizeCup: brandedCup = {
brandName: "스타벅스",
size: "grande",
};
9. Literal type
- 기본 타입의 값들을 조합해서 한정적인 값들만 나타내는 타입을 만들 수 있음.
type CoffeeSize = "small" | "medium" | "large";
let myCoffeeSize: CoffeeSize = "small";
let starbucksCoffeeSize: CoffeeSize = "tall"; // 타입 에러
10. Function type
- JS와 TS에서는 함수를 값처럼 사용할 수 있음. 즉 어떤 변수에 함달된 값이 함수라면 그 타입은 함수 타입.
function echo(message: string): string {
console.log(message);
return message;
}
const funcEcho = echo; // 함수를 값에 할당
type = FuncEcho = (message: string) => string;
const funcEcho2: FuncEcho = echo;
** 함수타입을 타입 별칭으로 지정할 수도 있음
type FuncEcho3 = {
(message: string): string; // => 가 없는 것에 주의
};
const funcEcho3: FuncEcho3 = echo;
funcEcho3("test3"); // 함수의 타입을 자동으로 추론해 실행
funcEcho3(123); // 매개변수가 문자열이 아니므로 타입 에러