코로 넘어져도 헤딩만 하면 그만
Typescript 들어가기 전 주말공부 본문
Typescript는 javascript 개선한 업그레이드 버전이라고 보면 된다. 따로 타입을 지정 안 해도 되는 포용력이 과하게 높은 자바 스크립트보다, strict하게 에러를 잡아주는 타입 스크립트의 중요성이 높아진다.
1) 자바스크립트는 dynamic typing 가능하기 때문에 5-'3'도 계산이 가능하다. 그러나 프로젝트 사이즈가 커지게 되면 이러한 자유도는 단점이 될 뿐이다. 타입 스크립트에서는 type error을 쓰면 이상하다고 말해준다.
2) 타입 스크립트로 엄격하게 타입을 체크하면서, 에러 메세지의 퀼리티가 올라가게 된다.
"자바스크립트가 아직까지 살아 남은 이유는 타입 스크립트가 산소 호흡기를 붙여두었기 때문이다."
-개발자 선배님 왈
🚩Typescript 적용하기
1) 파일은 무조건 .ts 파일로 생성해야 한다. 이 .ts파일은 못 읽히기 때문에 .js로 컴파일 해야 사용가능하다. new terminal에 tsc - w 라는 명령어를 입력하면 자동으로 js로 전환된다. 이걸 끄지 않으면 js가 생성되는 것을 볼 수 있다. html에 꽂으려면 js를 쓰면 된다.
2) tsconfig.json이라는 걸 생성한다. 아래 코드를 넣는다. js 몇 버전으로 컴파일 할 것인지 적어주는 것이다.
{
"compilerOptions" : {
"outDir": "dist", //dist라는 폴더 안에 앞으로 js를 다 넣어 줘
"target": "es5", //어떤 걸로 변환을 해줄래? es6도 가능
"module": "commonjs", //일반적인 js. React면 esnext
}
}
cmd+shift+B
변수를 만들 때에는 let 이름: string = 'kim'; 이렇게 타입을 지정해줘야 한다. 이 변수에는 문자만 들어올 수 있다는 의미. 타입을 엄격하게 관리한다. 숫자가 들어오면 에러가 바로 난다.
배열은 let 이름 : string[] = ['kim', 'park']; 이 내부에는 string만 들어오는 array라는 엄격한 뜻.
let 이름: Array<string>=['kim' , 'park']; 이런 식으로 표현도 가능하다.
객체는 let 이름 : {name : string } = {name : 'kim'};
name?를 하면 들어올 수도 있고 아닐 수도 있다는 뜻.
타입 스크립트에서는 아래와 같이 타입을 일일이 지정해준다.
웬만해서는 any 타입은 잘 쓰지 않는다....(이거 쓰면 뭐하러 타입 스크립트 씀?)
let 이름: string | number = 'kim'; //문자나 숫자가 들어올 수 있습니다.
type Mine = string | number; //이렇게 그냥 변수로 넣어서 쓸수도 있다. 대문자로 시작.
function 함수(x: number) : number {
return x * 2
} //number가 들어오고, number가 리턴되어야 한다.
type Member = [number, boolean];
let john: Member = [];
//무조건 첫째는 number, 둘째는 boolean이 들어와야 한다.
type Member = {
name : string
}
let john : Member = {name : 'kim'};
//무조건 문자만 들어오게 된다.
type Member = {
[key: string] : string
}
let john : Member = {name : 'kim', age : '3'};
//이런 식으로 모두에게 적용 가능
class User {
name: string;
constructor(name: string){
this.name = name;
}
}
하여간에 타입 스크립트는 정적 타입 언어이다. Java같이...
void는 아무것도 반환하지 않는 함수.(ex 콘솔만 찍음)
never은 영원히 끝나지 않거나 항상 에러를 반환하는 함수의 타입으로 씀.
enum은 비슷한 값들끼리 묶어준다.
🚩인터페이스 interface
type Score = 'A' | 'B' | 'C' | 'D' ;
interface User {
name: string;
age: number;
gender?: string;
readonly birthYear: number; //수정불가능
[key: number] : Score; //학년별 ? 적어줄 필요 없이 이렇게 키 설정 가능
}
let user : User = {
name: 'xx',
age: 30,
birthYear: 2000,
}
🚩인터페이스로 함수 정의하기
interface Add {
(num1: number, num2: number): number;
}
const add: Add = function(x, y) {
return x + y ;
}
// add (10, 20)
interface IsAdult {
(age: number): boolean;
}
const a:IsAdult = (age) => {
return age > 19;
}
a(33) // true
🚩인터페이스로 클래스 정의하기
//implements
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'){
console.log(b)
b.start();
}
//extends로 인터페이스 확장. 추가 가능.
interface Benz extends Car {
door: number;
stop(): void;
}
const benz: Benz = {
door: 5,
stop(){
console.log('stop')
},
color: 'black',
wheels: 4,
start (){
console.log('go...')}
}
function hello(name: string, age?: number): string { //age?가 먼저 앞에 와서는 안 된다.
if (age !== undefined){
return `Hello, ${name}. You are ${age}.`
} else {
return `Hello, ${name}.`}
}
타입 스크립트에서는 this도 타입을 입력해줘야 한다.
const userName1 = "Bob";
let userName2 : string | number = "Tom";
userName2=3;
type Job= "police" | "teacher";
interface User {
name: string;
job: Job;
}
const user : User = {
name: "Bob",
job: "teacher",
};
interface HighSchoolStudent {
name: number | string;
grade : 1|2|3;
}
🚩접근 제한자 public, private, protected
아무것도 작성하지 않으면 전부 public이다.
private는 자식 클래스 내부에서 사용할 수 없다.(#만 적기도 함)
protected는 자식 클래스에서는 참조 가능하지만 클래스 인스턴스에서는 참조 불가하다.
타입이 여러 개인데 전부 나열해 적는 게 비효율적일 때. Genetic을 사용한다. <> 로...
function getSize<T>(arr:T[]): number {
return arr.length;
}
const arr1 = [1,2,3];
getSize<number>(arr1);
const arr2=["a","b","c"];
getSize<string>(arr2);
//Genetic 의 역할, 하위에서 타입을 지정할 수 있게 해줌 <>
아래와 같이 인터페이스로 사용할 수도 있다.
interface Mobile<T> {
name: string;
price: number;
option: T;
}
const m1: Mobile<{color: string; coupon: boolean}> ={
name: "s21",
price: 1000,
option: {
color: "red",
coupon: false,
}
}
const m2: Mobile<string> = {
name: "s20",
price: 900,
option: "good",
}
🚩자주 사용되는 유틸리티 타입
Partial / Required / Readolny/ Record / Pick / Omit / Exclude / NonNullable
type Grade = "1" | "2" | "3" | "4";
type Score = "A" | "B" | "C" | "D" | "F";
const score: Record<Grade, Score> = {
1: "A",
2: "B",
3: "D",
4: "C",
};
//이런 식으로 Record <K,T> 처럼 키와 값을 사용할 수 있다.
interface User {
id: number;
name: string;
age: number;
}
//Pick과 Omit
const admin: Pick<User, "id" | "name"> = {
id: 0,
name: "Bob",
}
//Omit으로 바꾸면 제외가 가능함. 키를 제거.
//Exclude<T1, T2> 타입1에서 타입2를 제거
type T1 = string | number | boolean;
type T2= Exclude <T1, number | string>; //boolean
//NonNullable<Type>
type T1 = string | null | undefined | void;
type T2 = NonNullable<T1>; //string, void만 남는다.
React에서 타입 스크립트 쓰기
컴포넌트의 리턴값이 함수인 경우,
const App:React.FC = () => {
...
}
//이런 식으로 함수를 지정해줄 수 있다.
타입 스크립트는 원하는 모양으로 직접 타입을 만들어줄 수 있다. type / interface 로 만들어줄 수 있음. 두개 차이가 크게 있진 않은데. 하여튼.
useState는 아래와 같이 타입을 지정 가능하다.
const [myApp, setMyApp] = useState<number>(data);
//useState 쓸 때에는 Genetic 방식으로 설정해줄 수 있음.
보통 props 불러올 때에 받아온 것에 타입은 따로 준다.
interface OwnProps {
info: Restaurant,
changeAddress(address: Address):void, //리턴되는 값 없음
}
//이런 식으로 info와 changeAddress함수를 넘겨 받았을 때 props 타입을 지정 가능
interface는 반복되는 부분을 extends로, type는 &로 확장 가능. 단, 타입은 Omit 등을 사용해서 원하는 걸 쉽게 제외할 수 있다는 장점.
다음 주 본격적으로 TypeScript를 배우기 전에 주말에 혼자 이거저거 보면서 정리해본 결과... 아직 부족하겠지만...
있다가 공식 문서도 한번 봐야겠다.
'CODE STATES 44' 카테고리의 다른 글
Redux 기초 노마드 코더 정리(1) (0) | 2023.05.28 |
---|---|
rfce 네 글자로 컴포넌트 기본 세팅: 익스텐션 추천 (0) | 2023.05.28 |
산타5 프로젝트 라이브 요약 (0) | 2023.05.27 |
styled-component 설치 시 갑자기 뜨는 에러 (0) | 2023.05.27 |
왜 리액트는 Happy Hacking일까? (0) | 2023.05.27 |