뉴히의 개발 로그
[TIL] 20230727 - react-typeScript 프로젝트 생성 / typeScript 복습 타입스크립트 타입정리 및 예시 (기본타입,Tuple,union,intersection,void, never,enum,public, private, protected,abstract,Generic,keyof,Partial,Required,Readonly,Reco.. 본문
[TIL] 20230727 - react-typeScript 프로젝트 생성 / typeScript 복습 타입스크립트 타입정리 및 예시 (기본타입,Tuple,union,intersection,void, never,enum,public, private, protected,abstract,Generic,keyof,Partial,Required,Readonly,Reco..
뉴히 2023. 7. 27. 20:34리액트 타입스크립트 프로젝트 생성
공식문서 https://create-react-app.dev/docs/adding-typescript/
// npx를 사용하는 경우
npx create-react-app my-app --template typescript
// yarn을 사용하는 경우
yarn create react-app my-app --template typescript
기존 작업하던 리액트 프로젝트에서 시작
// npx를 사용하는 경우
npm install --save typescript @types/node @types/react @types/react-dom @types/jest
// yarn을 사용하는 경우
yarn add typescript @types/node @types/react @types/react-dom @types/jest
프로젝트 생성 완료 !
기본타입
let age:number = 123;
let isAudult:blooean = true;
let a2:number[] = [1,2,3]
let a2:Array<number≥ [1,2,3];
let week1:string[] = [’mon’, ‘tue’, ‘wed’];
let week2:Array<string> = [’mon’, ‘tue’, ‘wed’];
함수 컴포넌트 리턴 타입 :React.FC
// 튜플 (Tuple)
let b : [string,number,boolean] = [’안녕’,’123’,true]
- 타입선언한것과 순서가 동일하게 들어가야함
- b[0].toUpperCase ⇒가능 (스트링타입이기 때문에 ) | b[1].toUpperCase ⇒ 오류!
// union | (또는)
type Job = ‘police’ | ‘developer’ | ‘teacher’;
// 교차타입 intersection types & (and)
interface Car {
name: string;
start(): void;
}
interface Toy {
name: string;
color: string;
price: number;
}
const toyCar: Toy & Car = {
// 모든 인터페이스의 속성을 적어줘야함
name:'타요',
start(){},
color: 'blue',
price: 1000
}
// void, never
콘솔만 찍히고 아무것도 반환하지 않을때 void 타입 사용
function sayhello(): void {
console.log(’hello’);
}
에러만 찍히거나 계속 끝나지 않는 함수의 타입으로 never 사용
function showError(): never {
throw new Error();
}
function infLoop(): never {
while(true){
// do something..
}
}
// enum : 비슷한 값끼리 묶어준것이라고 생각하면됨
enum Os {
window, // 0
Ios, // 1
Android // 2
}
// 선언을 안해주면 자동으로 0,1,2... 으로 0부터 +1로 증가하면서 할당
enum Os {
window =3, // 2
Ios, // 4
Android // 5
}
enum Os {
window =3, // 2
Ios=10, // 10
Android // 11
}
양방향으로 맵핑되어있다!
console.log(OS['Ios']) // 10
console.log(OS[10]) // 'Ios'
enum Os {
window = 'win',
Ios ='ios',
Android = 'and'
}
// String의 경우 단방향으로 맵핑된다
let myOs:Os;
myOs = Os.Window
enum Os 안에있는 값만 사용할 수 있다.
// null, undefined
let a:null = null;
let b:undefined = undefined;
객체 타입 생성 방법
- interface
- type
interface 프롭스명 extends 상위선언타입 { }
type 프롭스명 = 상위선언타입 & { }
type Score = 'A' | 'B' | 'C' | 'F' ;
interface User {
name: string;
age: number;
gender?: string; // 옵셔널 처림 ? 있어도 되고 없어도 됨, 있을시에는 string
readonly birthYear: number;
// [grade(key-별의미없음): number]: string; // number를 키로 받고 string으로 value를 받겟다
[grade: number]: Score; // string은 너무 방대하기때문에 타입을 새로 선언해서 A,B,C,F로 한정해서 지정할수있다.
}
let user: User = {
name: '길동',
age: 30,
birthYear: 2000, // readonly 타입 -> 생성시 할당
1: 'A',
2: 'B'
};
user.age = 10;
user.gender = 'male'
user.birthYear = 1990; // 에러 ! readonly 속성이기 때문에 생성시에만 할당가능
* **interface로 함수 정의**
interface Add {
(num1: number, num2:number) : nember ; // (인자값1, 인자값2) : 리턴값의 타입
}
const add : Add = function(x, y) { //num1, num2로 안받아도 됨!
return x + y;
}
add(10, 20); // 30
* **나이를 받아서 성인인지 아닌지 boolean 타입으로 리턴받는 함수**
interface IsAdult {
(age:number) : boolean;
}
const a:IsAdult = (age) =>{
return age > 19;
}
a(33); // true
// * **interface로 Class 정의**
interface Car {
color: string;
wheels: number;
start(): void;
}
class Bmw implements Car {
color;
wheels = 4;
**** // 생성시에 입력받기
****constructor(c:string){
this.color = c;
}
start(){
console.log('go..')
}
}
const b = new Bmw('green');
**// 확장**
interface Benz extends Car {
door: number; // 추가 속성
stop(): void;
}
const benz: Benz = {
door: 5,
stop() {
console.log('stop');
},
wheels: 4,
color: 'red',
start() {
console.log('dd');
}
}
**// 여러 인터페이스 동시 확장 가능**
interface Car {
color: string;
wheels: number;
start(): void;
}
interface Toy {
name: string;
}
interface ToyCar extends Car, Toy {
price : number;
}
// 클래스 접근 제한자(Access modifier) - public, private, protected
- public - 자식 클래스, 클래스 인스턴스 모두 접근 가능
- protected - 자식 클래스에서 접근 가능
- private - 해당 클래스 내부에서만 접근 가능 ⇒ private 대신 ‘#변수명’으로 사용 가능
readonly 속성 : public 에서 속성을 수정할 수 없고 읽기만 가능하게
⇒ 수정할 수 있게하려면 construtor 안에서 미리 작업을 할 수있게 만들어줘야함
static 속성 : 정적 멤버 변수를 만들 수 있다.
⇒ static으로 선언된 정적 멤버 변수나 메서드는 “this.변수명” 이 아니라 “클래스명.변수명” 으로 접근해야한다.
// 추상 class (abstract)
추상 클래스는 new를 이용해서 객체를 생성할 수 없다. extends(상속)을 통해서만 생성할 수 있다.
상속받은 객체에서 구체적인 기능을 꼭 정의해줘야한다!
abstract class Car {
color: string;
constructor(color: string) {
this.color = color;
}
start() {
console.log('start');
}
abstract doSomething():void; // 속성이나 메서드 이름만 선언! 자식 클래스 에서 정확한 기능 정의
}
// const car = new Car("red"); // 에러!!
class Bmw extends Car {
constructor(color: string){
super(color); // super 없으면 에러남!!
}
doSometing(){ // abstract class를 상속받았으니 여기 구체적인 기능을 꼭! 정의해 줘야한다
alert(3);
}
}
// 제네릭 Generic : <T> 타입 파라메터, X or A등 사용해도 무관
- 제네릭을 이용하면 클래스나 , 함수, 인터페이스를 다양한 타입으로 재사용 가능하다.
- 선언시에는 type parameter만 정해주고 생성시점에 사용하는 타입을 결정!
function getSize<T>(arr: T[]): number {
return arr.length;
}
const arr1 = [1,2,3];
getSize<number>(arr1); // 3
getSize<number | string>(arr1); 이렇게 사용 할 수도 있다.
const arr2 = ['a','b','c'];
getSize<string>(arr2); // 3
const arr3 = [false, true, false];
getSize<boolean>(arr3); // 3
const arr4 = [{},{},{ name: 'Tim'}];
getSize<object>(arr4); // 3
// * interface에서 사용예시
interface Mobile<T> {
name: string;
price: number;
option: T;
}
// const m1:Mobile<{color: string; coupon: boolean }> = { // 모습이 정해져 있으면 이렇게 해도 됨
const m1:Mobile<object> = {
name: 's21';
price: 1000;
option: {
color: 'red',
coupon: false,
},
};
const m2: Mobile<string> = {
name: 's21';
price: 1000;
option: 'good'
};
유틸리티 타입
// keyof
interface User {
id: number;
name: string;
age: number;
gender: "m" | "f";
}
type UserKey = keyof User; // 'id' | 'name' | 'age' | 'gender'
const uk: UserKey = "id"; // 이런식으로 쓸수 있움
// Partial<T>
- property를 모두 옵셔널로 바꿔줌 ⇒ 일부만 사용 가능
- 그외 속성을 추가하려하면 에러남!
// Required<T>
- 모든 속성을 필수로 바꿔줌!
// Readonly<T>
- 읽기 전용 속성으로 바꿔줌, 처음에 할당만 가능하고 후에 수정은 불가
// Record<K, T>
// 사용 예시
type Grade = "1" | "2" | "3" | "4";
type Score = "A" | "B" | "C" | "D" | "F";
const score: Record<Grade, Score> = {
1: "A",
2: "C",
3: "B",
4: "D"
}
// 사용 예시
interface User {
id: number;
name: string;
age: number;
}
function isValid(user: User) {
const result: Record<keyof User, boolean> = {
id: user.id >0,
name: user.name !== "",
age: user.age > 0
};
return result;
}
// Pick<T,K> : T타입에서 K 속성만 골라서 사용
interface User {
id: number;
name: string;
age: number;
gender: "M" | "W";
}
const admin: Pick<User, "id" | "name"> = {
id: 0,
name: "Bob"
}
// Omit<T,K> : T타입에서 K 속성만 제외하고 사용
interface User {
id: number;
name: string;
age: number;
gender: "M" | "W";
}
const admin: Omit<User, "age" | "gender"> = {
id: 0,
name: "Bob"
}
// Exclude<T1, T2>
: Omit 은 속성만 제거, Exclude는 타입을 제거( 겹치는 타입을 제거)
type T1 = string | number | boolean;
type T2 = Exclude<T1, number | string>; // T2는 boolean 만 남음
// NonNullable<Type>
: null, undefined 제외 시킴
type T1 = string | null | undefined | void;
type T2 = NonNullable<T1>; // T2는 string | void 만 남음