[React] React JS 마스터클래스 #6 STATE MANAGEMENT(2) - React Hook Form
보호되어 있는 글입니다.
2023.07.12
no image
[Typescript] Typescript로 블록체인 만들기 #4 CLASSES AND INTERFACES
Constructor(생성자) 파라미터들을 써주기만 하면 TypeScript가 알아서 Constructor 함수를 만들어줌 class로부터 객체를 생성할 때 호출되고 객체의 초기화를 담당 TypeScript class Player { constructor( private firstName:string, private lastName:string ) {} } JavaScript class Player { constructor(firstName, lastName) { this.firstName = firstName; this.lastName = lastName; } } 자바스크립트에서는 접근제한자가 사라짐. 하지만 TypeScript에서는 에러가 생기기전에 코드를 보호해줌 ex) nico.firstName ..
2023.07.03
[Typescript] Typescript로 블록체인 만들기 #3 FUNCTIONS 과제 답안
보호되어 있는 글입니다.
2023.06.30
no image
[Typescript] Typescript로 블록체인 만들기 #3 FUNCTIONS
호출 시그니쳐 (Call Signatures) call signatures란 함수 이름 위에 마우스를 올렸을 때 뜨는 파라미터 타입 정보와 리턴 타입 정보로 함수를 어떻게 호출해야 하는지와 반환 타입도 알려줌. 함수 인수에 타입을 넣고싶지 않을 때 사용 함수의 call signature 타입 만드는 법 type Add = (a:number, b:number) => number; const add:Add = (a,b) => a+b; const add:Add = (a,b) => {a+b}; //Error! Type 'void' is not assignable to type 'number' 오버로딩(over loading) 함수가 서로 다른 call signatures를 가지고 있을 때 발생함. 외부 패키지나..
2023.06.29

[React] React JS 마스터클래스 #6 STATE MANAGEMENT(2) - React Hook Form

2023. 7. 12. 22:43

This is a protected article. Please enter the password.

Constructor(생성자)

파라미터들을 써주기만 하면 TypeScript가 알아서 Constructor 함수를 만들어줌

class로부터 객체를 생성할 때 호출되고 객체의 초기화를 담당

  • TypeScript
class Player {
    constructor(
        private firstName:string,
        private lastName:string
    ) {}
}
  • JavaScript
class Player {
    constructor(firstName, lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }
}
자바스크립트에서는 접근제한자가 사라짐.
하지만 TypeScript에서는 에러가 생기기전에 코드를 보호해줌
ex) nico.firstName //TypeScript에서는 Error가 발생하지만 자바스크립트에선 문제없음

 

class Player{
	constructor(
    	private firstName:string,
        private lastName:string,
        public nickname:string
    ) {}
}

const nico = new Player("nico", "las", "니꼬");

 

Abstract Class(추상클래스)

추상클래스: 다른 클래스가 상속받을 수 있는 클래스로 오직 다른 곳에서 상속받을 수만 있고 직접 인스턴스를 생성하지 못함!

abstract class User{
	constructor(
    	private firstName:string,
        private lastName:string,
        public nickname:string
    ) {}
    getFullName(){
    	return '${this.firstNme} ${this.lastName}'
    }
}

class Player extends User {

}

 

Abstract Method(추상함수)

메소드를 추상클래스 안에서 구현하지 않고 메소드의 call signature만 적어둬야 함

abstract class User{
	constructor(
		protected firstName:string,
		protected lastName:string,
		protected nickname:string
	) {}
	abstract getNickName():void
	getFullName(){
		return '${this.firstNme} ${this.lastName}'
	}
}

class Player extends User {
	getNickName(){
		console.log(this.nickname);
	}
}

 

Access Modifiers(접근 제한자)

  • public : 클라스의 외부에서 접근 가능
  • private : 클라스 내에서만 접근 가능, 클라스의 외부에서 접근 불가능
  • protected : 클라스 내부, 그리고 상속받은 자식 클라스에서 접근 가능

 

type Words = {
	[key:string]: string
}

let dict: Words = {
	"potato" : "food"
	1 : "food	//Error!
}

-> Words는 타입이 string만을 property로 가지는 오브젝트임

 

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");

 

readonly (읽기전용)

public 이지만 더 이상 변경할 수 없도록 만들 때 사용

주로 다른 누군가가 데이터를 덮어쓰는걸 방지하기 위해서

class Word{
	constructor(
    	public readonly term: string,
        public readonly def: string
    ){}
}

const kimchi = new Word("kimchi", "한국의 음식");
kimchi.def = "xxx" //Error!

 

Interface

  • type : 오브젝트의 모양을 묘사하는데 쓸 수도 있고 타입 alias를 만들 수 있음
type Team = "red" | "blue" | "yellow"
type Health = 1 | 5 | 10

type Player = {
	nickname : string,
	team : Team,
	health : Health
}

const nico : Player = {
	nickname : "nico",
    team : "pink", //Error!
    health : 5
}
  • interface : 오브젝트의 모양을 특정해주기 위해 사용
interface Player {
	nickname : string,
	team : Team,
	health : Health
}

What is the difference between a type and an interface?

> Interfaces can only be used to type an object, a Type can be used for any type.

(인터페이스는 오로지 오브젝트의 모양을 타입스크립트에게 설명해주기 위해서만 사용되는 키워드임)

 

abstract class User{
    constructor(
        private firstName:string,
        private lastName:string,
    ) {}
    abstract sayHi(name:string):string
    abstract fullName():string
}

class Player extends User {
    fullName(){
    	return '${this.firstName} ${this.lastName}'
    }
    sayHi(name:string){
    	return 'Hello ${name}. My name is ${this.fullName()}'
    }
}

What is the difference between an abstract class and a "normal" class?

> We can't make an instance of an abstract class. but Abstract class will become a normal class in JS.

추상 클래스는 인스턴스 만드는 것을 허용하지 않음.  new User() //Error!

추상 클래스는 단지 상속받는 클래스가 어떻게 동작해야할지 알려주기 위해(표준화하기위해)서 사용됨

하지만 자바스크립트에서는 abstract의 개념이 없기 때문에 일반적인 클래스로 바꿔버림.

  • javascript (abstract -> class)
class User {
    constructor(firstName, lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }
}
class Player extends User {
    fullName() {
        return '${this.firstName} ${this.lastName}';
    }
    sayHi(name) {
        return 'Hello ${name}. My name is ${this.fullName()}';
    }
}

 

인터페이스는 컴파일하면 자바스크립트에서 바뀌지않고 사라짐

interface User{
    firstName:string,
    lastName:string
    sayHi(name:string):string
    fullName():string
}

class Player implements User{
    constructor(
        public firstName:string,
        public lastName:string,
    ) {}
    fullName(){
    	return '${this.firstName} ${this.lastName}'
    }
    sayHi(name:string){
    	return 'Hello ${name}. My name is ${this.fullName()}'
    }
}
class Player {
    constructor(firstName, lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }
    fullName() {
        return '${this.firstName} ${this.lastName}';
    }
    sayHi(name) {
        return 'Hello ${name}. My name is ${this.fullName()}';
    }
}

하지만 인터페이스를 상속하면 private property들을 사용하지 못하고 매번 constructor를 선언해줘야한다는 문제점이 있지만

인터페이스를 만들어두고 원하는 각자의 방식으로 클래스를 상속할 수 있다는 장점도 있음

 

Polymorphism(다형성)

제네릭을 사용하여 다형성(다른 모양의 코드를 가질 수 있게 해줌)을 이룰 수 있음

제네릭을 클래스로 보내면 클래스는 제네릭을 인터페이스로 보내줄 수 있음

 

  • 일반적인 자바스크립트에서 사용한 로컬 스토리지 API와 같은 API를 가지는 클래스 만들기
interface SStorage<T> {
	[key:string]: T
}

class LocalStorage<T> {
    private storage: SStorage<T> = {}
    set(key:string, value:T){
    	this.storage[key] = value;
    }
    remove(key:string){
    	delete this.storage[key]
    }
    get(key:string):T {
    	return this.storage[key]
    }
    clear(){
    	this.storage = {}
    }
}

const stringsStorage = new LocalStorage<string>();
stringsStorage.get("key");	//get(key: string): string
stringsStorage.set("hello", "how are you"); //set(key:string, value:string): void

const booleansStorage = new LocalStorage<boolean>();
booleansStorage.get("key");	//get(key: string): boolean
stringsStorage.set("hello", true);
728x90

[Typescript] Typescript로 블록체인 만들기 #3 FUNCTIONS 과제 답안

2023. 6. 30. 20:22

This is a protected article. Please enter the password.

호출 시그니쳐 (Call Signatures)

call signatures란 함수 이름 위에 마우스를 올렸을 때 뜨는 파라미터 타입 정보와 리턴 타입 정보로

함수를 어떻게 호출해야 하는지와 반환 타입도 알려줌. 함수 인수에 타입을 넣고싶지 않을 때 사용

 

함수의 call signature 타입 만드는 법

type Add = (a:number, b:number) => number;
const add:Add = (a,b) => a+b;

const add:Add = (a,b) => {a+b}; //Error! Type 'void' is not assignable to type 'number'

 

오버로딩(over loading)

함수가 서로 다른 call signatures를 가지고 있을 때 발생함. 외부 패키지나, 라이브러리 사용시 많이 사용됨

 

오버로딩 예시1) 파라미터 타입이 다른 경우

type Config = {
    path: string,
    state: object
}
type Push = {
    (path:string): void
    (config:Config): void
}

const push:Push = (config) => {
    if(typeof config === "string") { console.log(config)}
    else {
        console.log(config.path, config.state)
    }
}

 

오버로딩 예시2) 파라미터 개수가 다른 경우

type Add = {
    (a: number, b: number): number
    (a: number, b: number, c: number): number
}

const add:Add = (a, b, c?: number) => {
	if(c) return a+b+c
    return a+b
}
  • 다른 개수의 파라미터를 가지게 되면, 나머지 파라미터도 타입을 지정해줘야 함
c?: number c는 아마도 number일 것이다.

 

다형성(polymorphism)

type SuperPrint = {
	(arr: number[]):void
	(arr: boolean[]):void
	(arr: string[]):void
}

const superPrint: SuperPrint = (arr){
	arr.forEach(i => console.log(i));
}

superPrint([1,2,3,4])
superPrint([true, false, true])
superPrint(["a", "b", "c"])

기존의 존재하는 타입(String, boolean, number..)인 concrete type 대신 generic 타입을 받을 거라고 알려줄거임

generic이란?

타입의 placeholder 같은 것으로 concrete type을 사용하는 것 대신 쓸 수 있음

타입스크립트로 placeholder를 작성할 수 있고 그게 뭔지 추론해서 함수를 사용하는 것

 

generic을 사용하는 이유

call signature를 작성할 때, 여기 들어올 확실한 타입을 모를 때 generic을 사용

 

generic 사용법

타입스크립트에 generic을 사용하고 싶다고 알려줘야함 : <generic명칭>

type SuperPrint = {
	<TypePlaceholder>(arr: TypePlaceholder[]):void
}

const superPrint: SuperPrint = (arr){
	arr.forEach(i => console.log(i));
}

superPrint([1, 2, 3, 4])
superPrint([1, 2, true, false])

 

  • generic을 여러개 선언할 수 있음

1) 제네릭을 사용할거라고 알려주고 이름을 작성함

2) 어디서 이 제네릭을 사용할건지 알려줘야함

type SuperPrint = <T,M>(a: T[], b: M) => T

const superPrint: SuperPrint = (a) => a[0]

superPrint([1,2,3,4], "x")

function superPrint<T>(a: T[]) {
    return a[0]
}

const a = superPrint([1, 2, 3,4])
const b = superPrint<boolean>([true, false, true]); //직접 타입을 전달할 수도 있음

 

  • 제네릭을 사용해 타입을 확장할 수 있음 -> 재사용 가능
type Player<E> = {
	name: string
	extraInfo: E
}
type NicoExtra = {
	favFood: string
}
type NicoPlayer = Player<{ favFood: string }>

const nico: Player<{favFood: string}> = {
	name: "nico"
	extraInfo: {
    	favFood: "kimchi"
   	}
}

const lynn: Player<null> = {
	name: "lynn",
	extraInfo: null
}

 

728x90