📌js에서 설치
npm install -g typescript
터미널에 설치
파일이름.ts
파일 생성
tsconfig.json
파일생성 후 내부에 아래내용 작성
//tsconfig.json은 ts->js컴파일시 옵션설정가능하다
{
"compilerOptions":{
"target":"es5",
"module":"commonjs",
}
}
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로 작성한 파일을 넣으면 된다
타입스크립트는 두가지 접근방식이 있다
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(별칭타입)이 필요
타입은 변수에 담아 쓸수있다
보통 타입변수 첫글자는 대문자로 작명
어떤 타입에도 적용할 수 있다
🚨 주의사항:같은 이름의 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 TypeFun=(a:string)=> number
let 함수:TypeFun=function(){ //함수표현식에만 type alias사용가능
return 10
}
항상 정해진 갯수의 요소를 가져야하는 array를 지정할 수 있다
인덱스 별로 타입이 다를때 사용
//예제1)
const player:[string,number,boolean]=["nico",1,true]
//예제2)
type Member = [number, boolen];
let john: Member = [123, true];
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" };
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()
}
function hello(){ //:void로 타입을 지정해주지 않아도 TS가 void로 인식한다
console.log("x")
}
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%확실할 때 쓴다
오브젝트를 특정하는 방법은 두가지가 있다
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}
함수타입은 ()=>{}
로 만들 수 있다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타입을 쓰는 이유는 변수에 뭐가 들어올지 더 엄격하게 관리가 가능하다
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자료를 완전히 잠궈놓고 싶을 때 사용한다~~
narrowing 연산자를 사용해서 html element를 조작할 수 있다
변수 조작하기 전에 null인지 아닌지 캐치하기위해 tsconfig.json파일에서 strickNullCheck옵션을 켜고 시작
설렉터로 html을 찾으면 타입이 Element|null 이다
따라서 narrowging 연산자를 이용해야 조작이 가능하다
//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 = '반가워요';
}
let 링크 = document.querySelector('#link');
if (링크 instanceof HTMLAnchorElement) { //html 태그 종류별로 정확한 타입명칭을 작성해주어야한다
링크.href = 'https://kakao.com'
}
let 버튼 =document.querySelector("#button")
버튼?.addEventListener("click", function(){
})
a태그는 HTMLAnchorElement
img태그는 HTMLImageElement
h4태그는 HTMLHeadingElement
등등