04. type annotation, type inference
type annotation
개발자가 타입을 타입스크립트에게 직접 말해주는것const rate: number = 5
type inference
타입스크립트가 알아서 타입을 추론하는것const rate = 5
타입을 추론하지 못해서 타입 annotation을 꼭 해줘야하는 경우
- any타입을 리턴하는경우
coordinates에 hover해보면const json = '{"x": 4, "y": 7}' const coordinates = JSON.parse(json) console.log(coordinates)
const coordinates: any
라고 뜨는것을 볼 수 있다. JSON.parse는 json을 파싱해준다. 인풋으로 들어가는 json을 확인하면 대충 어떤 타입이 리턴될지 개발자는 예상할 수 있지만, 타입스크립트는 여기까지 지원하지 않는다. 리턴 타입이 일정하지 않으므로 any를 리턴한다고 추론해버린다. 그러므로 이경우에 타입 annotation을 해주어야한다. - 변수 선언을 먼저하고 나중에 초기화 하는 경우
변수 선언과 동시에 초기화하면 타입을 추론하지만, 선언을 먼저하고 나중에 값을 초기화할때에는 추론하지 못한다.let greeting greeting = 'hello' // let greeting: any
- 변수에 대입될 값이 일정치 못한 경우
여러타입이 지정되어야 할 때에는|
(or statement)로 여러 타입을 annotation해준다.let num = [-7, -2, 10] let numAboveZero: boolean | number = false
for(let i = 0; i <num.length; i++) {
if(num[i] > 0) {
numAboveZero = num[i]
}
}
## 05. 타입스크립트 개발 환경 구성
설치할것 : code editor(VS), nodejs, npm(nodejs설치시 같이 설치됨)
폴더생성
타입스크립트설치 `npm install -g typescript`
`tsc main.ts`를 하면 js로 컴파일되면서 main.js가 생성된다.
그 main.js를 html파일에서 열어주면 됨.
처음은 ES3 문법으로 컴파일되는데 ES6로 버전으로 컴파일할 수 있게 따로 설정가능하다.
`tsc main.ts -w`로 watch설정을 하면 수정하고 저장될때마다 자동 컴파일된다.
## 06. tsconfig.json 설정하기
tsconfig.json 만들고
```json
{
"compilerOptions": {
"rootDir": "./src", // 소스 파일 안에서 root폴더 명시
"outDir": "./build/js", // ts 컴파일 후에 어느 경로로 들어가는지 명시
"target": "ES2015", // 타입스크립트를 ES2015버전의 자바스크립트로 변환
"noEmitOnError": false, // 파일에 에러가 있을 때에는 컴파일 하지 않는 옵션
"module": "ESNext", // 컴파일을 마친 후 자바스크립트가 사용한은 모듈 시스템
"moduleResolution": "Node",
"esModuleInterop": true, // ESM(ES Module), CommonJS 호환해서 사용 가능
"lib": ["ESNext", "DOM"], // 컴파일 과정에서 사용하는 라이브러리 지정
"strict": true, // 타입스크립트 파일에 타입을 엄격하게 사용한다고 명시
},
"include": [ // 소스파일의 어디에서 타입스크립트 파일을 찾을 수 있는지 명시
"./src/**/*.ts", // src 폴더안에 모든 하위 경로, 모든 ts 파일
],
"exclude": [ // 컴파일시 제외할 목록
"node_modules"
]
}
- rootDir 설정
- outDir 설정
- src폴더 안의 파일만 컴파일 설정하기 : include에서 src안의 모든 ts파일 설정
- noEmitOnError: false 에러가 있더라고 파일이 emit된다.
07. 타입들 사용해보기
// boolean
let boolean: boolean
let falseBoolean: boolean = false
// number
let number: number
let integer: number
let float:number = 1.234
// string
let string: string
let firstName: string ="Doe"
// Array
// 한가지 타입만 가지는 배열
let names1: string[] = ["John", "Kim"]
let names2: Array<string> = ["John", "Kim"]
// 여러 타입을 가지는 배열(union)
let array1: (string | number)[] = ['John', 1, 2]
let array2: Array<string | number> = ['John', 1, 2]
// 여러타입을 단언할수없다면 any
let someArray = ['John', 1, [], {}, false];
// interface, type
// 읽기전용 배열(readonly, ReadonlyArray)
let stringArray: readonly string[] = ['A', 'B', 'C']
let numberArray: ReadonlyArray<number> = [1, 2, 3]
stringArray.push('C') // error
numberArray[0] = 3 // error
// Tuple 배열과 비슷하지만 해당자리의 타입과 고정된 길이를 지켜야함
let tuple1: [string, number]
tuple1 = ['a', 1]
tuple1 = ['a', 1, 2] // error
tuple1 = [2, 'a']; // error
let users: [number, string][]
users = [[1, 'John'], [2, 'Doe']]
let tuple2: [string, number]
tuple2 = ['a', 1]
tuple2.push(2) // 허용된 타입일경우 push로 값을 넣는것 가능
console.log(tuple2)
// any
let any: any = 'abc'
any = 1
any = []
// unknown
let unknown: unknown = false
let string1: string = unknown // error 다른 값에 할당불가
let string2: string = unknown as string // 타입단언하면 가능
// object
let obj: object = {}
let arr: object = []
let nul: object = null // error. typeof null은 'object'로나오긴하지만
let date: object = new Date()
const obj1: {id: number, title: string} = {
id: 1,
title: 'title1',
description: 'description' // error
}
// Union
let union: (string | number)
union = 'hi'
union = 1
union = [] // error
// Function
let func1: (arg1: number, arg2: number) => number
func1 = function(x, y) {
return x * y
}
let func2: () => void
func2 = function() {
console.log('Hellow world')
}
// Null, undefined
// strict이 false일때 전부 가능함
let number1: number = undefined
let string4: string = null
let object: {a: 10, b: false} = undefined
let array: any[] = null
let null1: null = undefined
let void1: void = null
let void2: void = undefined // 가능
// void
function greeting(): void {
console.log("hi")
}
// never
function keepProcessing(): never {
while(true) {
console.log("hi");
}
}
const never: [] = []
never.push(1) // error
const never2: number[] = []
never2.push(1) // 가능_텍스트_
08. 타입 단언(type assertion)과 타입 Guard
타입 단언(type assertion)이란?
Typescript에선 시스템이 추론 및 분석한 타입 내용을 우리가 원하는대로 얼마든지 바꿀 수 있다. 이때 타입단언이라 불리는 매커니즘이 사용된다.
type assertion을 사용하면 값의 type을 설정하고 컴파일러에 이를 유추하지 않도록 지시할 수 있다. 이것은 프로그래머로서 typescript가 자체적으로 추론할 수 있는것보다 변수 유형에 대해 더 잘 이해하고 있을때입니다.
var foo = {};
foo.bar = 123; // error
foo.bas = 'hello'; // error
컴파일러는 foo 타입이 속성이 없는 {}라고 가정하기 때문에 컴파일러 오류가 발생한다.
아래와 같이 type assertion을 사용하면 이러한 상황을 피할 수 있다.
interface Foo {
bar: string;
bas: string;
}
var foo = {} as Foo;
foo.bar = 123;
foo.bas = 'hello';
타입단언 예제
// 1. 타입 단언
const bodyElement = document.querySelector('body') as HTMLBodyElement;
bodyElement.innerText = "Hello";
// 2. ! not null 타입 단언
const bodyElement1 = document.querySelector("body");
bodyElement1!.innerText = "Hello"; // undefined나 null 이 아니다!
// 3. type guard
const bodyElement2 = document.querySelector("body");
if(bodyElement2) {
bodyElement2.innerText = "Hello";
}
잘못된 타입단언
function func(arg: string | null) {
return (arg as string).toLowerCase()
}
func('hello');
func(null); // error
arg를 string으로 단언하는데 null이 들어가면 컴파일에러가 난다.
type guard를 넣어 수정하면된다.
function func(arg: string | null) {
if(arg) {
return (arg as string).toLowerCase()
}
}
func('hello')
func(null)
09. Type Alias vs Interface
Type Alias와 Interface는 타입의 이름을 지정하는 방법으로 매우 유사하고 대부분의 경우 자유롭게 선택할 수 있다.
차이점
Interface의 확장: extends를 이용
interface Animal {
name: string;
}
interface Bear extends Animal {
honey: boolean;
}
const bear1: Bear = {
name: 'honey bear',
honey: true
}
Type의 확장: Intersection을 이용
type Animal = {
name: string;
}
type Bear = Animal & {
honey: boolean;
}
const bear1: Bear = {
name: "honey bear",
honey: true,
};
Interface 선언 병합(Declaration Merging)
interface는 되지만 type alias는 선언병합이 안된다.
interface Animal {
name: string;
}
interface Animal {
honey: boolean;
}
const bear1 = {
name: 'honey bear',
honey: true
}
공통점
Implements 사용가능
Type과 interface 모두 클래스에 implements를 사용할 수 있다.
interface IArticle {
category: string;
content: string;
}
class Article implements IArticle {
public category = "";
public content = "";
}
type IArticle2 = {
category: string;
content: string;
}
class Article2 implements IArticle {
public category = "";
public content = "";
}
Union
Union 유형을 사용하면 개발자가 타입A 또는 타입B가 될 수있는 새 Type를 만들수있다. |
연산자를 사용하여 Type과 Interface를 모두 사용하여 새로운 Union 유형을 생성한다. 그러나 선언은 항상 type이어야 한다.
// interface
interface Animal {
name: string;
}
interface Bear extends Animal {
honey: boolean;
}
type NewType = Animal | Bear;
const bear1: NewType = {
name: "honey bear",
honey: true,
};
// type
type Animal2 = {
name: string;
}
type Bear2 = Animal & {
honey: boolean;
}
type NewType2 = Animal | Bear;
const bear2: NewType2 = {
name: "honey bear",
honey: true,
};
'Frontend > Javascript・Typescript' 카테고리의 다른 글
[Typescript] 단언 연산자 느낌표 !(타입단언) (0) | 2024.02.08 |
---|---|
[Typescript] Typescript Essentials3 (1) | 2023.11.01 |
[Typescript] Typescript Essentials1 (1) | 2023.11.01 |
[Jquery]사이즈에 따른 반응형 스크립트 / colspan setAttribute (0) | 2021.12.15 |
jquery scrollTo 부드럽게 스크롤 (0) | 2021.10.24 |