<TS>Typescript 설치와 기초

yezee·2022년 12월 1일
0

TS

목록 보기
1/5
post-thumbnail
post-custom-banner

설치

📌js에서 설치
npm install -g typescript 터미널에 설치
파일이름.ts 파일 생성
tsconfig.json 파일생성 후 내부에 아래내용 작성

//tsconfig.json은 ts->js컴파일시 옵션설정가능하다
{
    "compilerOptions":{
        "target":"es5",
        "module":"commonjs",
    }
}
  • 파일 변경
    브라우저는 JS파일 밖에 읽을줄 모르기 때문에 TS파일을 JS로 전환시켜주어야한다
    js파일 -> .ts
    jsx파일 -> .tsx
    tsc-w 자동변환 명령어

📌 React 프로젝트에서 TS사용할 경우
1.이미 있는 리액트 프로젝트에 설치
npm install --save typescript @types/node @types/react @types/react-dom @types/jest @types/react-router-dom

2.그냥 리액트 프로젝트를 새로 만들거면
새로 작업폴더를 하나 만들고 거기서 에디터와 터미널을 오픈한다음 아래 명령어 입력
npx create-react-app my-app --template typescript

  • tsconfig.json은 뭐하는 파일이에요??
    Ts->JS 컴파일 시 옵션설정가능
  • 콘솔창에서 열어보고 싶어요
    html 파일에 ts로 작성한 파일을 넣으면 된다

필수문법

간단한 변수 타입지정가능 👉 string,number,boolean,null,undefined,bigint,[],{} 등

타입스크립트는 두가지 접근방식이 있다
1.implicit(추론타입) - let b="hello" (b가 string타입이라고 추론하고 있기 때문에 다른타입할당불가)
2.explicit(명시적타입) - let a:boolean="x" (boolean타입으로 명시하였기 때문에 다른타입할당불가)
(ts가 타입을 추론하지 못할경우 명시적표현을 해주는 것이 좋다
하지만 보통 명시적 표현은 최소한으로 하는것이 좋다(ts가 추론하는 것이 더 낫다))

-명시적타입-

:타입지정

//이 변수엔 string type만 들어올수있다
let 이름: string = 'kim';

//이 변수엔 string이 담긴 array만 들어올 수 있다
let a: number[] = [1,2,3];
let a2:Array<number>=[1,2,3];

let week1=string[]=["mon","tue","wed"]
let week2=Array<string>=["mon","tue","wed"]

-선택적 변수-

?를 앞에 붙이면 optional
변수?:number는
볌수:number | undefined와 같다

const player:{
  name:string,
  age?:number //를 붙이면 옵션이기 때문에 (age는 number이거나 undefind)
}={
  name:"nico"
  //age가 없어도 에러가 나지 않는다
}

if(player.age && player.age<10){} //player.age는 undefind일 수 있기 때문에 있다는가정 &&를 표시해줘야 에러가 뜨지 않는다
//object타입지정
//name뒤에 ?는 "name속성은 옵션이라는것을 뜻한다" 
//다른게 들어와도 에러가 나지 않는다 또는 name없이 age만 있어도 에러가 나지 않는다(name은 있어도 없어도 그만인 옵션이기 때문)
let 객체: { name?: string, age:number } = { name: 'park' ,age:12};

//다양한 타입이 들어올 수 있게 하려면 union type
let 다양해: string | number = 'kim';

근데 player가 엄청 많다면 타입지정을 계속 반복해줘야한다
그래서 Alias(별칭타입)이 필요

-Alias Type(타입변수)-

타입은 변수에 담아 쓸수있다
보통 타입변수 첫글자는 대문자로 작명
어떤 타입에도 적용할 수 있다
🚨 주의사항:같은 이름의 type변수 재정의 불가능

//예제1)
type Player={ //type변수에 name과 age의 타입을 지정해주었다
	name:string,
    age?:number
}

const nico:Plyer={
	name:"nico"
}

const lynn:Plyer={
	name:"lynn",
  	age:12
}

type alias extend하기

//OR연산자 예제1)
type Name=string;
type Age=number;
type Person =Name | Age

//&연산자 예제2)
type PositionX ={x:number}
type PositionY ={y:number}

type NewType=PositionX & PositionY //{x:number,y:number}
let position:NewType={x:10,y:20}
  • type에 함수type저장해서 쓰는방법
type TypeFun=(a:string)=> number

let 함수:TypeFun=function(){ //함수표현식에만 type alias사용가능
  return 10
}

-array에 쓸수있는 tuple타입-

항상 정해진 갯수의 요소를 가져야하는 array를 지정할 수 있다
인덱스 별로 타입이 다를때 사용

//예제1)
const player:[string,number,boolean]=["nico",1,true]

//예제2)
type Member = [number, boolen];
let john: Member = [123, true];

-그밖에 다양한 TS타입들-

  • Union type
    타입2개 이상 합친 새로운 타입(가변적인 타입)
let member:number|string =123 //숫자 또는 문자 둘다 사용가능하다 

//예제2)array,object자료 만들 때 uniontype 쓰는방법
let member:(number|string)[]=[1,"2",3]
let object:{a:string|number}={a:"123"}

object 타입에 지정해야할 속성이 너무 많으면?

글자로 된 모든 object속성의 타입은 string

type Member = {[key: string]: string};
let john: Member = { name: 'kim', food:"pizza" };
  • readonly
    readonly가 있으면 최초 선언 후 수정불가(불변성을 부여)
const names:readonly string[]=["1","2"]
name.push() //값을 변경하려는 순간 에러가 발생한다
  • undefined&null&any
    undefined:선언x,할당x
    null:선언o, 할당x
    any:모든 자료형 허용(타입실드 해제문법)

  • unknown
    변수의 타입을 미리 알지 못할 때 unkonwn을 사용한다
    모든 값을 나타내기 때문에 any와 비슷하지만 any보다 안전하다(이유는 unknown값으로 작업을 수행하는 것이 합법적이지 않기 때문)

let a:unknown

if(typeof a=== "number"){
 let b=a+1
}
if(typeof a=== "string"){
 let b=a.toUpperCase()
}
  • void
    아무것도 return하지 않는 함수를 대상으로 사용
    함수가 예외를 throw하거나 프로그램 실행을 종료함을 의미
function hello(){ //:void로 타입을 지정해주지 않아도 TS가 void로 인식한다
	console.log("x")
}
  • never
    함수가 절대 return하지 않을 때 발생
function hello():never{
	return "x" //오류가 발생하게 된다
}
function hello(name:string|number){
  if(typeof name==="stirng"){
     name//여기의 name은 stirng이다
  }else if(typeof name==="number"){
    name//여기의 name은 number이다
  }else{
  	name //여기의 name은 naver이다(즉, 이코드는 절대 실행되지 않아야한다는 것)
  }
}

-함수에 타입지정-

파라미터와 return값의 타입을 지정할 수 있다
타입이 지정된 파라미터는 필수로 넣어주어야한다

//예제1)
// 이 함수는 파라미터로 number, return 값으로 number로 타입지정
function 함수(x: number): number {
  return x * 2;
}

//예제2)

type Player={
	name:string,
    age?:number
}
function playerMaker(name:string):Player{
	return{
    name:name
    }
}

const nico=playerMaker("nico")
nico.age=12

에러나는 이유를 찾아보자!🧐

function 함수(x:number|string):void{
 console.log(x+3) //에러가 발생한다
}
함수(2)

이유는 타입스크립트는 엄격하기 때문에
string+number(가능)
number+string(가능)
이외에는 불가능하다
근데 지금 x값은 number|string타입이라 불가능하다
에러를 없애려면~ 애매한 타입들은 미리 타입검사필요!!

function 함수(x:number|string):void{
  if(typeof x === "number"){
    console.log(x+3) //에러가 없어진다(narrowing)
  } 
}
함수(2)
  • 타입확정하기

1)Narrowing
if문 등으로 타입을 하나로 정해주는 것을 뜻한다
Narrowing으로 판정해주는 문법들 typeof변수, 속성면 in 오브젝트자료, 인스턴스 instanceof 부모

2)Assertion
타입 덮어쓰기

function 내함수(x:number|string){
  let array:number[]=[]
  array[0] =x as number //assertion문법
}

이렇게 편한대 왜 narrowing쓰는겨??
assertion문법의 용도는
1.타입을 변경하는게 아니라 narrowing할때 쓴다
2.무슨 타입이 들어올지 100%확실할 때 쓴다

-interface-

오브젝트를 특정하는 방법은 두가지가 있다
1. type 이름={}
2. interface 이름 {}

오직 오브젝트 모양을 특정해주기 위해 사용

//예제1)
type Score="A"|"B"|"C"|"D" //유니온타입

interface User{
  name:string;
  age:number;
  gender?:string;
  [grade:number]:Score
}
let user:User={
  name:"xx",
  age:30,
  1:"A"
   
}
  • 인터페이스에는 상속기능이 있다
//인터페이스를 상속하는 방법은 객체지향 프로그래밍의 컨셉과 유사하다
interface Student{
    name:string
}

interface Teacher extends Student{ //class와 닮았다
    age:number
}
let 학생:Student={name:"kim"}
let 선생:Teacher={name:"kim",age:20}
  • 인터페이스로 함수2개 넣기
    함수타입은 ()=>{}로 만들 수 있다
interface MathObj {
  plus : (a:number, b:number) => number,
  minus : (a:number, b:number) => number
}

let 오브젝트 :MathObj = {
  plus(a,b){
    return a + b
  },
  minus(a,b){
    return a - b
  }
} 

interface와 Type Aliases의 차이점

  • Type Aliases는 인터페이스의 거의 모든 기능을 type에서 사용할 수 있으며 주요 차이점은 type을 다시 열어 새 속성을 추가할 수 없다(중복선언 불가능)
  • interface는 항상 확장이 가능하다(중복선언가능)
interface Student{name:string}
interface Student{score:number} //속성추가가 매우쉽다
Student //{name:string,score:number}

-literal type으로 만드는 const-

literal타입을 쓰는 이유는 변수에 뭐가 들어올지 더 엄격하게 관리가 가능하다

let 이름:123; //아예 값을 타입으로 박아버리는 것

그럼 const변수랑 뭐가 다르나요??
const는 값이 하나이지만 literaltype을 쓰면 여러개의 값을 가질 수 있다

많이하는실수!

var 자료={name :"kim"}
function 내함수(a:"kim"){
}
내함수(자료.name) //이럼 에러가 난다

에러가 나는 이유는 함수는 "kim"타입만 입력가능
자료.name이라는 거는 string타입이지 "kim"타입이 아니기 때문

해결법은 as const

var 자료={name:"kim"} as const //뒤에 as const를 붙이면 에러해결

1.타입을 objext의 value로 바꿔준다(타입을 "kim"으로 바꿔준다)
2.object안에 있는 속성을 readonly로 바꿔준다
즉, object자료를 완전히 잠궈놓고 싶을 때 사용한다~~

-html 변경과 조작-

narrowing 연산자를 사용해서 html element를 조작할 수 있다
변수 조작하기 전에 null인지 아닌지 캐치하기위해 tsconfig.json파일에서 strickNullCheck옵션을 켜고 시작

설렉터로 html을 찾으면 타입이 Element|null 이다
따라서 narrowging 연산자를 이용해야 조작이 가능하다

  • h4글자를 바꿔보자
//narrowing
let 제목 = document.querySelector('#title');
if (제목 != null) {
 제목.innerHTML = '반가워요';
 }

//instanceof 연산자
let 제목 = document.querySelector('#title');
  if (제목 instanceof Element) {
  제목.innerHTML = '반가워요';
}

//as(assertion)
let 제목 = document.querySelector('#title') as Element;
제목.innerHTML = '반가워요';

//optional chaining
let 제목 = document.querySelector('#title')
if (제목?.innerHTML != undefined) {
  제목.innerHTML = '반가워요';
}
  • href 속성을 바꿔보자
let 링크 = document.querySelector('#link');
if (링크 instanceof HTMLAnchorElement) { //html 태그 종류별로 정확한 타입명칭을 작성해주어야한다
  링크.href = 'https://kakao.com'  
}
  • 이벤트리스터 달기
    optional chaining으로 narrowing하면 간단하게 쓸 수 있다
let 버튼 =document.querySelector("#button")
버튼?.addEventListener("click", function(){
    
})

a태그는 HTMLAnchorElement
img태그는 HTMLImageElement
h4태그는 HTMLHeadingElement
등등

profile
아 그거 뭐였지?
post-custom-banner

0개의 댓글