Typescript로 블록체인 만들기 강의를 토대로 정리한 내용입니다.
Typescript
타입스크립트는 자바스크립트기반으로 만들어진 언어
자바스크립의 여러문제를 해결하고 보완하기 위해 만들어진 언어
strongly-typed언어 - 프로그래밍 언어가 작동하기 전에 type을 확인한다.
Typescript 사용하면 좋은점
- 코드에 버그가 줄어든다.
- 더 나은 개발자경험을 제공한다.
타입의 종류
let a:number
let b:string
let c:boolean
// array type
let a:number[]
let a:string[]
let a:boolean[]
//object type
const player : {
name: string,
age: number
} = {
name: 'aa',
age: 17
}
// object type (property이름은 모르지만 타입만 알고있는 경우)
// 많이 사용된다.
type Words = {
[key: string]: string //key에는 아무 문자열이 와도 된다.
};
let dict: Words = {
"potato": 'food'
}
//optional type
const player : {
name: string,
age?: number //있을수도 있고 없을수도 있는 optional 값
} = {
name: 'aa',
}
type alias 설정
타입을 여러군데에서 공통으로 사용한다면 type alias를 사용하는 것을 권장한다.
타입을 재사용할 수 있게 해준다.
type alias 의 첫번째 문자는 대문자로 써주기!
type Player = {
name: string,
age?: number
}
const player : Player = {
name: 'aa'
}
const player2 : Player = {
name: 'bb'
age: 18
}
return 하는 값 타입 정해주기
type Player = {
name: string,
age?: number
}
// return하는값 타입으로 함수 뒤에 :하고 타입을 명시해 준다.
function playerMaker(name: string) : Player {
return {
name
}
}
const nico = playerMaker("nico");
nico.age = 12;
readonly 속성을 추가할 수있다.
type Player = {
readonly name: string,
age?: number
}
// return하는값 타입으로 함수 뒤에 :하고 타입을 명시해 준다.
function playerMaker(name: string) : Player {
return {
name
}
}
const nico = playerMaker("nico");
nico.age = 12;
nico.name = 'aa'; //error
Tuple
array를 생성할 수있게 한다.
최소한의 길이를 가져야하고 특정위치에 특정타입이 있어야한다.
const player: [string, number, boolean] = ["nico", 1, true];
//readonly
const player: readonly [string, number, boolean] = ["nico", 1, true];
any
아무타입이나 허용한다.
사용하지 않는 것을 추천. any를 사용하면 자바스크립트 코드로 사용하는 것과 같다.
unknown
어떤 타입이 오는지 모르는 변수를 사용할 때
해당 변수로 어떤 작업을 하려면 이변수의 타입을 먼저 확인해야한다.
let a:unknown;
if (typeof a === 'number'){
let b = a + 1;
}
if(typeof a === 'string'){
let b = a.toUpperCase();
}
void
아무것도 return하지 않는 함수를 대상으로 한다.
보통 void는 따로 지정해 줄 필요는 없다.
function hello() {
console.log('hello');
}
never
절대 실행되지 않아야한다.
function Hello(name: string | number) {
if(typeof name === string) {
name //string
} else if(typeof name === number) {
name //number
} else {
name //never
}
}
event객체
타입스크립트에서는 e.target(이벤트가 일어난 target) 대신 e.currentTarget(이벤트가 bind된 target)을 사용한다.
이유는 요 블로그에 잘 정리되어있다. https://nuhends.tistory.com/115
이벤트 객체에 타입을 명시해 줄 때 아래 코드처럼 작성해 주면된다.
해당 이벤트 어떤 이벤트인지 확인하고 싶을 때
react syntheticEvent 참고
// <>안에 들어가는 값은 어디에서 이벤트가 발생했냐
event: React.FormEvent<HTMLInputElement>
event: React.MouseEvent<HTMLButtonElement>
call signatures
함수위에 마우스를 올렸을 때 가이드 문구로 보게 되는 것
인자타입이랑 함수의 반환타입을 알려준다.
// 방법1
type Add = (a: number, b: number) => number;
// 방법2
type Add = {(a: number, b: number) : number};
const add:Add = (a, b) => a + b;
오버로딩(overloading)
오버로딩은 여러 call signatures가 있는 함수
type Add = {
(a: number, b: number) : number
(a: number, b: string) : number
}
const add: Add = (a, b) => {
if(typeof b === 'string') return a;
return a + b;
}
받는 파라미터 개수가 다른 경우
공통으로 받는 파라미터가 아닌경우는 옵셔널 처리를 해줘야한다.
type Add = {
(a: number, b: number) : number,
(a: number, b: number, c: number) : number,
}
// c 옵셔널 처리를 해줘야한다.
const add:Add = (a, b, c?:number) => {
if(c) return a + b + c;
return a + b
}
다형성
다형성이란 ? 다른모양의 코드를 가질수있게 해주는 것
다형성을 이룰 수 있는 방법? 제네릭 사용
제네릭 (generic)
타입의 placeholder
타입이 뭔지 추론해서 타입기준으로 바꿔준다.
call signature를 작성할 때 확실한 타입을 모르는 경우 사용한다.
<> 안에 원하는 placeholder명을 넣어주면 된다.
type SuperPrint = {
<TypePlaceholder>(arr: TypePlaceholder[]) : TypePlaceholder
}
// generic이 두개 오는 경우
type SuperPrint = <T, M>(a: T[], b: M) => T;
type SuperPrint = {
<T>(arr: T[]):T
};
const superPrint:SuperPrint = (arr) => {
return arr[0]
}
superPrint([1, 2, 3]);
superPrint(['1', '2', '3']);
superPrint(['1', '2', 3, true]);
type Player<E> = {
name: string,
extraInfo: E
}
type NickPlayer = Player<{favFood: string}>
const nick:NickPlayer = {
name: 'nico',
extraInfo: {favFood: 'kimchi'}
}
제네릭 사용해서 타입선언
type A = Array<number> //number[] 이렇게 사용할 수도 있다.
let a:A = [1, 2, 3, 4];
classes
private, public, protected
자바스크립트에는 없는 개념
타입스크립트에서 검증을 하고 자바스크립트로 컴파일되기 때문에 안전하게 사용할 수있다.
class Test {
constructor(
private firstname: string,
private lastname: string,
public nickname: string
) {}
}
const test = new Test('nico', 'last', 'slRh');
test.nickname = 'ggg';
test.firstname = '하'; // Test 클래스 안에서만 수정가능한 private이므로 error
Private: 인스턴스 밖에서 접근할 수없고, 자식클래스에서도 접근할 수 없다.
다른자식 클래스에서 사용하고 싶다면 private를 사용하지 않는다.
Protected: 클래스 밖에서는 접근안됨, 자식클래스에서는 사용할수있다.
Public : private, protected 를 사용하지 않으면 public 이다.
property뿐만 아니라 method에서도 작동한다.
class Test {
constructor(
private firstname: string,
private lastname: string,
public nickname: string
) {}
private getFullName () {
return `${this.firstname} ${this.lastname}`;
}
}
const test = new Test('nico', 'last', 'slRh');
test.getFullName() //private속성이라 error
Abstract (추상클래스)
추상클래스는 오직 다른곳에서 상속받을수만 있는 클래스
자바스크립트에는 추상클래스 개념이 없다.
추상클래스를 사용하는이유 ?
표준화된 property와 메소드를 갖도록 해주는 청사진을 만들기위해 추상클래스를 사용한다.
abstract class User {
constructor(
private firstname: string,
private lastname: string,
public nickname: string
) {}
}
class Player extends User {
} // O
const test = new User('nico', 'last', 'slRh'); // error
추상메소드
추상메소드를 만들려면 메소드를 클래스안에서 구현하지 않으면 된다.
메소드의 call signature만 작성해야한다.
상속받는 곳에서 구현을 해야하는 메소드를 의미한다.
abstract class User {
constructor(
private firstname: string,
private lastname: string,
public nickname: string
) {}
abstract getNickname():void
}
class Player extends User {
getNickname() { //상속받는 클래스에서 구현을 해줘야한다.
return this.nickname;
}
}
const test = new Player('nico', 'last', 'slRh');
class객체를 타입으로 선언할 수 있다.
아래 코드에서 Word클래스를 타입으로 선언한걸 확인할 수있다.
type Words = {
[key: string] : string;
}
class Dict {
private words: Words;
constructor() {
this.words = {}
}
add(word: Word) {
if (this.words[word.term] === undefined) {
this.words[word.term] = word.def;
}
}
def(term: string) {
return this.words[term];
}
}
class Word {
constructor(
public term: string,
public def: string
) {}
}
const kimchi = new Word('kimchi', '한국의 음식');
const dict = new Dict();
dict.add(kimchi);
dict.def('kimchi');
Word 클래스의 property는 public사용하고 싶지만 수정이 안되게 할수있다.
readonly를 사용해서 읽기전용으로 만들어준다.
class Word {
constructor(
public readonly term: string,
public readonly def: string
) {}
}
type으로 특정 값 지정 할 수 있다.
type Team = 'red' | 'blue' | 'yellow';
type Player = {
name: string,
team: Team
}
const test: Player = {
name: 'ddd',
team: 'yellow' //Pink입력하면 error
}
interface 인터페이스
interface는 오로지 오브젝트의 모양을 타입스크립트에게 설명해 주기 위해서만 사용한다.
type은 다양한 용도로 더 많이 사용된다.
object type을 선언할때는 interface를 많이 사용한다. 이유는 밑에서 설명한다!
type Team = 'red' | 'blue' | 'yellow';
interface Player {
name: string,
team: Team
}
const test: Player = {
name: 'ddd',
team: 'yellow'
}
styled-components로 선언한 css컴포넌트에 interface 적용하기
interface ContainerProps {
bgColor: string;
}
const Container = styled.div<ContainerProps>`
background-color: ${(props) => props.bgColor}
`
타입상속
interface는 클래스 처럼 extends해서 상속한다.
interface User {
name: string
}
interface Player extends User {}
const nico: Player = {
name: 'nico'
}
type으로 사용할 때 상속
type User = {
name: string
}
type Player = User & {}
const nico: Player = {
name: 'nico'
}
property 축적
interface 3번 각각 만들면 타입스크립트가 하나로 합쳐준다. type은 지원하지 않는다.
interface User {
name: string
}
interface User {
lastName: string
}
interface User {
health: number
}
const nico:User = {
name: 'nico',
lastName: 'last',
health: 10
}
class 대신 interface를 써야하는 이유
1. 클래스는 아니지만 클래스의 모양을 특정할 수있게 해주는 간단한 방법
2. 자바스크립트로 컴파일 되면 없어지는 코드라 코드를 가볍게 만들어준다.
3. 추상클래스처럼 강제성도 줄 수있다. 선언된 property가 없으면 오류가 난다.
interface User {
firstName: string,
lastName: string,
sayHi(name: string): string,
fullName(): string
}
// class extends 대신 implements를 사용한다.
// type도 implements로 사용할 수 있다.
class Player implements User {
// 인터페이스를 상속할때는 private, protected 속성을 사용할수없다.
// pulic만 가능하다.
constructor(
public firstName: string,
public lastName: string,
) {}
sayHi(name: string){
return 'hi'
}
fullName() {
return `${this.firstName} ${this.lastName}`
}
}
여러가지 인터페이스를 상속하는 경우
interface User {
firstName: string,
lastName: string,
sayHi(name: string): string,
fullName(): string
}
interface Human {
healty: number
}
// interface 여러개 상속하는경우
class Player implements User, Human {
constructor(
public firstName: string,
public lastName: string,
public healty: number
) {}
sayHi(name: string){
return 'hi'
}
fullName() {
return `${this.firstName} ${this.lastName}`
}
}
useState 타입선언
기본적으로 처음에 default value값으로 들어간 데이터 타입을 확인하고 타입스크립트가 추론하지만
예외적으로 하나의 state에 문자열, 숫자가 동시에 들어가는경우는 타입을 선언해 줘야한다.
const [value, setValue] = useState<number | string>(0);
setValue(2);
setValue('안녕');
setValue(true); //error
enum (enumerable)
실수를 방지하기 위해 사용하는 상수같은 개념
값 할당없이 사용하는 enum에는 자동으로 0, 1, 2 값이 들어간다.
값을 지정하고 싶은경우 값 할당을 해주면 된다.
export enum Categories {
"TO_DO", //0 실제값
"DOING", //1
"DONE" //2
}
export enum Categories {
"TO_DO" = "TO_DO", //TO_DO
"DOING" = "DOING", //DOING
"DONE" = "DONE" //DONE
}
export const selectState = atom<Categories>({
key: 'select',
default: Categories.TO_DO
})
'TECH' 카테고리의 다른 글
redux개념 정리 (0) | 2023.02.16 |
---|---|
tsconfig.json 기본세팅, d.ts, JSDoc (0) | 2023.02.14 |
async, await 알아보기 (0) | 2022.03.30 |
프론트개발시 CORS 오류와 해결방법! (0) | 2022.03.20 |
Promise에 대해 알아보자! (0) | 2021.09.26 |