Typescript
function showTimes(arr) {
arr.forEach(element => {
console.log(element)
});
}
showTimes([1,2,3]) //1, 2, 3
showTimes(1,2,3) //error 발생
- Javascript(동적언어):
실행되는 시점 (런타임)에 타입이 결정되고 오류가 있을 시 그때 처리가 가능하다.
function showTimes(arr:number[]) {
arr.forEach(element => {
console.log(element)
});
}
showTimes([1,2,3]) //1, 2, 3
function showTimes(arr:string[]) {
arr.forEach(element => {
console.log(element)
});
}
showTimes([1,2,3]) //error
- Java, TypeScript(정적언어)
컴파일시에 타입이 결정된다.
코드 작성때 시간이 길어지지만, 생각하고 코드를 짠다면 안정적인 로직 작성이 가능하다.
정리하자면, 타입스크립트를 쓰는 이유?
javascript에 타입이 추가 된 것이다. 그로인해 코드가 올바르게 작동하는지 확인할 수 있다.
[javascript]
function showTime(arr){
arr.forEach((item) => {
console.log(item)
})
}
showTime([1, 2, 3])
showTime(1, 2, 3)
///1
///2
///3
/// error...
//런타임에서 타입이 결정 됨
[첫번째 예제 확인]
function add(num1:number, num2:number){
console.log(num1 + num2)
}
//add()
//add(1)
add(1,2)
//add('hello', 'world')
any타입이였던 인수가 number로 고정이 됐다.
인수의 개수가 맞지 않은 부분과 string의 함수 호출부분이 에러가 표시가 됐다.
함수를 만들 때 의도했던 방식 외에 다른 방법은 모두 에러라고 나온다.
몇개의 인수를 어떤 타입으로 전달해야하는지 일일이 코드를 뒤져볼 필요가 없다.
[두번째 예제 확인]
any: 아무 타입이나 가능하다. 도저히 어떤 타입인지 모를때 사용한다. 하지만 가급적이면 사용을 지양한다.
Expected 1 arguments, but got 3
한개의 인수만 필요한데 3개를 받았다는 에러 메세지이다.
function showTime(arr:number[]){
// arr: number의 배열을 받음
arr.forEach((item) => {
console.log(item)
})
}
showTime([1, 2, 3])
타입스크립트 기본 타입
원시타입
let car:string = 'bmw'
let age:number = 30
let isAdult:boolean = true
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']
week1.push(3)//error
let u:undefined = undefined
let n:null = null
- null과 undefined
모든 타입의 하위 타입으로 number 같은 타입에 할당할 수 있다.
strickNullChecks를 사용하게 되면 null과 undefined는 오직 any타입과 각자 자신타입에만 할당 가능하다.
참조타입
- object, array, tupple
object
타입을 지정해주면 지정된 값들만 넣을 수 있게 만들어야 한다.
타입이 길어질경우 가독성이 많이 떨어지기에 보통 타입을 따로 지정해서 사용한다.
- 각 타입 지정 방법: Type Alias & Interface, index signature
- type alias: type을 따로 만들어서 사용한다.
- index signature: [key: string] key값에 어떤 타입이 명세될줄 모르나 전부 string으로 타입을 지정하는 방식이다.
- union type: string | number 처럼 여러 타입을 같이 선언한다
[기본형]
let obj: {
name: string;
age: number;
} = {
name: 'dabin',
age: 22
}
[type alias]
type myType = {
name: string;
age: number;
}
let obj: myTpye = {
name: 'dabin',
age: 22
}
[Type Alias + Index Signature + Union Type]
type myType = {
[key: string]: string | number
}
let obj: myTpye = {
name: 'dabin',
age: 22
}
Array
javascript처럼 자유롭지 못하다.
[기본형]
let a:number[] = [1, 3, 5]
let b:Array<number> = [4, 6, 7]
let week1:string[] = ['mon', 'tue', 'wed' ]
let week2:Array<string> = ['mon', 'tue', 'wed' ]
week1.push('4')
[배열 다중 타입]
let arr: (string|number)[] = [1, '1']
튜플(Tuple)
배열과 비슷하다.
인덱스별로 타입이 다를 때 사용한다.
//배열의 첫번째 요소에는 string 두번째 요소에는 number을 입력할 수 있음]
let ab:[string, number];
ab = ['z', 1]
ab = [1, 'z'] //error
// 문자 => 숫자 toLowerCase
b[0].toLocaleLowerCase()
b[1].toLocaleLowerCase() //number에는 toLocaleLowerCase가 없음
// void, never
void, never
function sayHello():void{
console.log('hello')
}
- void는 함수에서 아무것도 반환하지 않을 때 주로 사용한다.
function showError():never{
throw new Error()
}
function infLoop():never{
while (true){
//do something...
}
}
- never는 영원히 끝나지 않는 함수나, 항상 에러를 반환하는 함수에서 사용할 수 있다.
enum
열거형으로서 비슷한 값들끼리 묶어준다.
특정값만 입력하게 강조하고 싶을 때 또한 그 값들이 공통점이 있을 때 사용한다.
enum Os{
Window,
Ios,
Android
}
각각 수동으로 값을 할당하지 않으면 자동으로 0부터 1씩 증가되며 값이 할당된다.
enum Os{
Window,
Ios = 3,
Android
}
값을 할당하게 되면 해당 값부터 차례대로 값이 출력되는걸 알 수 있다.
window는 건너뛰고 값을주면 window는 0이된다.
console.log(Os[3]) // [LOG]: "Ios"
console.log(Os['Ios']) // [LOG]: 10
컴파일된 결과를 보면 OS라는 객체가 생성되고 양방향으로 내편되어 있다.
enum에는 숫자가 아닌 물자도 입력이 가능한데, 이럴때는 양방향이 아닌 단방향 맵핑만된다.
enum Os{
Window = 'win',
Ios = 'ios',
Android = 'and'
}
// 숫자가 아닌 문자열도 입력할 수 있다. 이럴 경우 단방향 맵핑만 된다.
let myOs : Os;
//myOs에는 Os에 있는 window, ios, Android만 사용할 수 있게 된다.
myOs = Os.Window //특정값만 입력할 수 있게 할 수 있다.
인터페이스(interface)
let user:object;
user = {
name: 'xx',
age: 30
}
console.log(user.name)
//콘솔에 있는 name부분이 빨간줄이 그어진다.
object에는 특정 속성값에 대한 정보가 없기때문에 에러가 발생한다.
interface User{
name: string,
age: number,
}
let user2: User={
name: 'xx',
age: 30
}
user2.age = 10
console.log(user2.age)
interface를 통해서 객체의 property를 정의해서 표현해준다.
[property 추가]
interface User{
name: string,
age: number,
gender? : string,
}
있어도되고 없어도 되는 속성을 추가하고 싶을 때는 optional chaining 사용한다.
(* optional chaining: 프로퍼티가 없는 중첩 객체를 에러 없이 안전하게 접근할 수 있다. )키 값뒤에 ? 를 넣어준다.
interface User{
name:string,
age:number,
gender?: string // 입력을 해도 되고 안해도 되는 속성은 optional을 사용한다.
}
let user: User = {
name: 'xxx',
age: 30
}
user.age = 10
user.gender = "male" //error
console.log(user.name)
만약 gender라는 property가 있을 때는 무조건 string이여야 한다.
[readOnly]
값에 접근할 수 는 있지만 수정은 불가능하다.
interface User{
gender? : string,
readonly birthYear: number
}
let user2: User={
age: 30,
birthYear: 2000
}
user2.birthYear = 1999
console.log(user2.birthYear)
user2.birthYear = 1999를 입력하면 에러가 뜨게된다.
읽기 전용 속성이라 수정할 수 없다.
[문자열 index 속성]
interface User{
gender? : string,
age: number,
readonly birthYear: number
1? : string;
2? : string;
3? : string;
4? : string;
}
let user2: User={
age: 30,
birthYear: 2000,
1: 'A'
}
학년별로 interface를 정의해줄 수 있다.
하지만, 1학년만 쓰고 싶을 때는 optional chaining 쓸 수 바께 없다.
이럴 경우에 문자열 index 속성을 사용하면 된다.
type Score = 'A' | 'B' | 'C' | 'F'
interface User{
gender? : string,
age: number,
readonly birthYear: number
//[grade: number] : string
[grade: number] : Score
}
let user2: User={
age: 30,
birthYear: 2000,
1: 's', //에러발생
2: 'B'
}
// 학년별로 interface를 정의해줄 수 있다.
[grade: number] : string 학년은 숫자로 받음 : 학점은 string
number를 key로 하고 string value로 받는 property를 여러개 만들 수 있다.
만약 학점을 String으로 받기에는 범위가 너무 넓은데 이럴 때 사용할 수 있는게
문자 리터럴이다.
type Score = 'A' | 'B' | 'C' | 'F'
이렇게 추가하게 되면 Score의 입력값만을 사용할 수 있다.
[interface로 함수 정의]
interface Add {
// (num1: number, num2: number): void
(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 > 10
}
console.log(a(7)) //false
console.log(a(11)) //true
[interface로 클래스 정의]
- [implements]
interface Car{
color: string
wheels: number
start(): void
}
class Bmw implements Car {
color = "red"
wheels = 4
}
- error가 발생한다. 속성값을 모두 입력해야 하기때문에 start()의 함수도 같이 정의를 해줘야 한다.
interface Car{
color: string
wheels: number
start(): void
}
class Bmw implements Car {
color = "red"
wheels = 4
start(){
console.log('gogogo')
}
}
- [constructor 이용]
interface Car{
color: string
wheels: number
start(): void
}
class Bmw implements Car {
color
wheels = 4
// 생성될 때 색상을 입력 받기
constructor(c:string){
this.color = c
}
start(){
console.log('gogogo')
}
}
const b = new Bmw('blue')
console.log(b)
//[LOG]: Bmw: {
"wheels": 4,
"color": "blue"
}
- [extends]
인터페이스는 확장이 가능하다. 그럴 때 extends 키워드를 사용한다.
interface Car{
color: string
wheels: number
start(): void
}
interface Benz extends Car{
door:number
stop(): void
}
const benz : Benz = {
door: 5,
stop(){
console.log('benz!')
}
}
console.log(benz.stop())
//에러가 발생된다.
왜 에러가 발생될까?
interface확장 전 Car의 속성들도 모두 입력을 해야한다.
interface Car{
color: string
wheels: number
start(): void
}
interface Benz extends Car{
door:number
stop(): void
}
const benz : Benz = {
door: 5,
stop(){
console.log('benz!')
},
color:"blank",
wheels: 4,
start(){
console.log('gogo')
}
}
console.log(benz.stop)
참고로 확장은 여러개를 할 수 있다.
동시 확장이 가능하다.
interface Car{
color: string
wheels: number
start(): void
}
interface Toy {
name: string
}
interface ToyCar extends Car, Toy{
price: number
}
'programming language > TypeScript' 카테고리의 다른 글
연산자를 이용한 타입 정의_유니온, 인터섹션 (1) | 2022.12.06 |
---|---|
타입스크립트 interface (0) | 2022.12.04 |
ts any, void (0) | 2022.12.03 |
타입스크립트 변수와 함수 타입 정의 (1) | 2022.12.03 |
tsc 컴파일 (0) | 2022.12.02 |
댓글