typeScript interface, Generic (+terminal 조금)

김내현·2025년 2월 12일

개인공부

목록 보기
46/51

Interface

인풋 객체에 대한 타입/ 특징을 미리 정의

💡

특징?

객체의 속성, 속성 타입
함수의 파라미터
함수의 파라미터, 반환 타입
배열, 객체 접근법
클래스

  1. 사용법
interface 인터페이스_이름 {
  속성: 타입;
}

function foo(param: 인터페이스_이름)

// 예시
interface personAge {
  age: number;
}

function logAge(obj: personAge) {
  console.log(obj.age);
}
let person = { name: 'Capt', age: 28 };
logAge(person);
  1. 특징
// 옵션 속성
// 인터페이스에 정의된 속성을 옵셔널하게 설정
interface 인터페이스_이름 {
  속성?: 타입;
}

interface CraftBeer {
  name: string;
  hop?: number;  
}
// hop 속성이 없어도 오류가 나지 않음
let myBeer = {
  name: 'Saporo'
};
function brewBeer(beer: CraftBeer) {
  console.log(beer.name); // Saporo
}
brewBeer(myBeer);
// 읽기 전용 속성
interface CraftBeer {
  readonly brand: string;
}
// CraftBeer.brand 는 재할당이 불가
// 읽기 전용 배열
let arr: ReadonlyArray<number> = [1,2,3];
arr.splice(0,1); // error
arr.push(4); // error
arr[0] = 100; // error
// 마찬가지로 해당 배열 내용을 변경 불가
// 인터페이스에서 정의하지 않은 속성들을 추가로 사용하고 싶을 때
interface CraftBeer {
	brand?: string;
	[propName: string]: any;
}
// 함수 타입
interface login {
	(username: string, password: string): boolean;
	// caller: "" 접근 불가
}

let loginUser: login;
loginUser = function(id: string, pw: string) {
	console.log('로그인 했습니다.');
	return true;
}
// 클래스 타입
interface CraftBeer {
	beerName: string;
	nameBeer(beer: string): void;
}
// implements로 구현
class myBeer implements CraftBeer {
	beerName: string = "baby Quiness";
	nameBeer(b: string) {
		this.beerName = b;
	}
	constructor() {}
}
  • implements VS extends extends는 클래스 상속 문법인데 인터페이스 확장에도 사용 가능함
    1. extends - 부모 클래스 상속

      // 클래스 상속
      // Parent
      class Parent {
        public lastName: string = "An";
      
        public speakKorean() {
          console.log("안녕하세요");
        }
      
        public eatWithChopsticks() {
          console.log("젓가락으로 먹기");
        }
      }
      
      // Child
      // 다중 상속 불가
      class Child extends Parent {}
      let child = new Child();
      console.log(child.lastName); //An
      child.speakKorean(); //안녕하세요
      child.eatWithChopsticks(); //젓가락으로 먹기
      // 인터페이스 상속
      interface Person {
          name: string;
          age; number;
      }
      interface Address {
      	city: string;
      }
      interface Employee extends Person, Address {
          // Person의 모든 속성과 Address의 모든 속성을 물려 받음
          // 다중 상속 가능
          role: string;
      }
    2. implements - 클래스 타입 지정

      // interface 정의
      interface Person {
        name: string;
        think(): void;
        walk(): void;
        eat(): void;
      }
      // class 
      class Child implements Person {
        name: string = "Fomagran";
        
        think(): void {
          console.log("생각하기");
        }
        walk(): void {
          console.log("걷기");
        }
        eat(): void {
          console.log("먹기");
        }
      }
      const child = new Child()
      console.log(child.name); // Fomagran
      child.think() //생각하기
      child.walk() //걷기
      child.eat() //먹기

      https://stackoverflow.com/questions/38834625/whats-the-difference-between-extends-and-implements-in-typescript
      https://fomaios.tistory.com/entry/TS-Extends와-Implements-차이-Difference-between-extends-and-implements

      특징implementsextends
      용도인터페이스 구현클래스 상속 또는 인터페이스 확장
      사용 가능한 곳클래스만클래스와 인터페이스
      다중 사용 가능 여부여러 인터페이스를 구현할 수 있음클래스에서는 단일 상속만 가능, 인터페이스는 다중 상속 가능
      강제 여부클래스가 인터페이스의 모든 속성과 메서드를 반드시 구현해야 함부모 클래스의 속성 및 메서드는 자동으로 상속됨
      주요 키워드implementsextends
// 하이브리드 타입
interface CraftBeer {
	(beer: string): string;
	brand: string;
	brew(): void;
}

function myBeer(): CraftBeer {
	let my = (function(beer: string) {}) as CraftBeer;
	my.brand = 'Beer Kitchen';
	my.brew = function() {};
	return my;
}
let brewedBeer = myBeer();
brewedBeer('My First Beer');
brewedBeer.brand = 'Pangyo Craft';
brewedBeer.brew();

Generic

데이터 타입을 커스텀할 수 있는 기법 - 타입을 함수의 인수처럼 사용

  1. 사용하는 이유
// 들어온 타입대로 출력하고 싶음 
// input type은 상관 X -> 다만 input type === output type 하고 싶음
function getText(text: any): any {
  return text;
  // 다만 any로 하는 경우 input ==== output type 인 걸 추가 코드 없이 구현 불가!
	// 타입을 변수처럼 사용할수는 없을까?
}
  1. 사용법
// data type "T"를 인수로 받음
function getText<T>(text: T): T {
  return text;
}
// usage
getText<string>('hi');
getText<number>(10);
getText<boolean>(true);

getText<string>(); // function getText<string>(text: T) T {}
getText<string>('hi'); // function getText<string>(text: string) string {}
  1. 제네릭 제약조건
// 제약조건
// 특정 타입의 매서드, 속성 활용하지 못함
function logText<T>(text: T): T {
  console.log(text.length); // Error: T doesn't have .length
  return text;
}

//// 해결 - 인터페이스, 제약조건 사용
// 예시 1. length가 동작하는 인자만 넘겨받고 싶을 때 
interface LengthWise {
  length: number;
}

// generic type 제약 -> class extends랑 다fma 
// <T extends K> -> T가 K에 할당 가능해야한다.
function logText<T extends LengthWise>(text: T): T {
  console.log(text.length);
  return text;
}

// 예시 2. 두번째 인자를 첫번쨰 인자의 키로 설정
function getProperty<T, O extends keyof T>(obj: T, key: O) {
// keyof T = "a" | "b" | "c"
  return obj[key];  
}
let obj = { a: 1, b: 2, c: 3 };

getProperty(obj, "a"); // okay
getProperty(obj, "z"); // error: "z"는 "a", "b", "c" 속성에 해당하지 않습니다.

// 예시 3. 함수 제약 조건
function translate<T extends (a: string) => number, K extends string>(x: T, y: K): number {
	// x 함수는 (a: string) => number를 꼭 만족해야됨
	return x(y);
}

// 문자숫자를 넣으면 정수로 변환해주는 함수
const num = translate((a) => { return +a; }, '10');
console.log('num: ', num); // num : 10

ETC

typeof

객체 데이터를 객체 타입으로

const obj = {
   red: 'apple',
   yellow: 'banana',
   green: 'cucumber',
};

// 위의 객체를 타입으로 변환하여 사용하고 싶을때
type Fruit = typeof obj;
/*
type Fruit = {
    red: string;
    yellow: string;
    green: string;
}
*/

let obj2: Fruit = {
   red: 'pepper',
   yellow: 'orange',
   green: 'pinnut',
};
Q. Interface에서 사용가능?
const obj = {
  name: "Apple",
  color: "Red",
  price: 1.5,
};

// typeof로 타입 추출
type FruitType = typeof obj;

// 인터페이스에서 재활용
interface FruitInterface extends FruitType {}

keyof

객체 타입의 속성만 모아 유니온 타입으로 만들어 줌

type Type = {
   name: string;
   age: number;
   married: boolean;
}

type Union = keyof Type;
// type Union = name | age | married

const a:Union = 'name';
const b:Union = 'age';
const c:Union = 'married'
const obj = { red: 'apple', yellow: 'banana', green: 'cucumber' } as const;

// 위의 객체에서 red, yellow, green 부분만 꺼내와 타입으로서 사용하고 싶을떄
type Color = keyof typeof obj; // 객체의 key들만 가져와 상수 타입으로

let ob2: Color = 'red';
let ob3: Color = 'yellow';
let ob4: Color = 'green';

TypeScript에서 as**타입 단언(Type Assertion)**에 사용됩니다. 이는 컴파일러에게 "이 값은 내가 지정하는 타입으로 간주하라"고 명시적으로 알려주는 역할을 합니다.

as를 사용하면 TypeScript가 자동으로 추론한 타입 대신 개발자가 지정한 타입을 사용하게 됩니다.
여기서 as const는 상수로 간주하도록 지시하여 특정한 효과를 얻습니다.

추가로 해 볼만 한것

제너릭으로 forEach, map 매서드 구현하기
https://inpa.tistory.com/entry/TS-%F0%9F%93%98-%EC%8B%A4%EC%A0%84-%EB%9D%BC%EC%9D%B4%EB%B8%8C%EB%9F%AC%EB%A6%AC-%EC%A0%9C%EB%84%A4%EB%A6%AD-%ED%83%80%EC%9E%85-%EB%A7%8C%EB%93%A4%EC%96%B4%EB%B3%B4%EA%B8%B0

출처

https://inpa.tistory.com/entry/TS-📘-타입스크립트-Generic-타입-정복하기

https://inpa.tistory.com/entry/TS-%F0%9F%93%98-%ED%83%80%EC%9E%85%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-keyof-typeof-%EC%82%AC%EC%9A%A9%EB%B2%95

https://velog.io/@nanotoly/TypeScript-10-point

https://www.typescriptlang.org/docs/handbook/typescript-in-5-minutes.html

  • shell programming
    운영체제 프로그램 실행 및 조작을 위한 인터페이스
    1. cd → 디렉토리 이동
    ```jsx
    cd <가고자 하는 디렉토리 경로>
    cd    # 사용자 디렉토리로 이동
    cd /  # root 디렉토리로 이동
    cd ../A # 상위 디렉토리로 이동
    cd Desktop/wecode  # Desktop 하위 wecode 디렉토리로 이동
    ```
    
    1. ls → 현재 디렉토리 리스트 불러오기
    
    ```jsx
    ➜  ls  #현재 디렉토리에 있는 내용 출력
    django-tutorial       javascript_assignment study
    
    ➜  ls -a # 숨겨진 파일이나 디렉토리도 함께 보여줌
    .                     .DS_Store             django-tutorial       study
    ..                    .git                  javascript_assignment
    
    ➜  ls -l # 자세한 내용(권한, 포함된 파일 수, 소유자, 그룹, 파일크기, 수정일자, 파일이름)
    drwxr-xr-x@  4 LeeJongMin  staff  128  2  1 22:42 django-tutorial
    drwxr-xr-x@  4 LeeJongMin  staff  128  2  4 12:54 javascript_assignment
    drwxr-xr-x@ 19 LeeJongMin  staff  608  1  3 10:07 study
    
    ➜  ls -al # a와 l의 기능을 모두 포함
    total 16
    drwxr-xr-x   7 LeeJongMin  staff   224  2  4 12:53 .
    drwx------@ 47 LeeJongMin  staff  1504  2  5 17:25 ..
    -rw-r--r--@  1 LeeJongMin  staff  6148  2  1 22:42 .DS_Store
    drwxr-xr-x  14 LeeJongMin  staff   448  2  5 23:44 .git
    drwxr-xr-x@  4 LeeJongMin  staff   128  2  1 22:42 django-tutorial
    drwxr-xr-x@  4 LeeJongMin  staff   128  2  4 12:54 javascript_assignment
    drwxr-xr-x@ 19 LeeJongMin  staff   608  1  3 10:07 study
    ➜  ls -h -al # -h를 붙이면 K, M, G 단위의 파일크기를 사용하여 사람에게 보기 좋게 표시
    total 16
    drwxr-xr-x   7 LeeJongMin  staff   224B  2  4 12:53 .
    drwx------@ 47 LeeJongMin  staff   1.5K  2  5 17:25 ..
    -rw-r--r--@  1 LeeJongMin  staff   6.0K  2  1 22:42 .DS_Store
    drwxr-xr-x  14 LeeJongMin  staff   448B  2  5 23:45 .git
    drwxr-xr-x@  4 LeeJongMin  staff   128B  2  1 22:42 django-tutorial
    drwxr-xr-x@  4 LeeJongMin  staff   128B  2  4 12:54 javascript_assignment
    drwxr-xr-x@ 19 LeeJongMin  staff   608B  1  3 10:07 study
    ```
    
    1. mv → 파일 옮기기/ 이름 변경 
    
    ```jsx
    ➜ mv <원본 파일명> <옮기고 싶은 디렉토리명>     # 해당 디렉토리로 파일 이동
    ➜ mv <원본 파일명> <바꾸고 싶은 파일명>         # 원본 파일 이름 변경
    ➜ mv <원본 디렉토리명> <옮기고 싶은 디렉토리명>  # 해당 디렉토리로 디렉토리 이동
    ➜ mv <원본 디렉토리명> <바꾸고 싶은 디렉토리명>  # 원본 디렉토리 이름 변경
    
    # 두 번째에 있는 옮기거나 바꾸고 싶은 파일/디렉토리명이 존재하면 '이동'이 진행되고, 없으면 '이름 변경'이 진행됨
    ```
    
    1. cp → 파일 복사
    
    ```jsx
    ➜ cp <원본 파일명> <옮기고 싶은 디렉토리명>               # 해당 디렉토리로 원본 파일 복사 
    ➜ cp <원본 파일명> <복사해서 만들고 싶은 파일명>           # 해당 파일명으로 사본 파일 생성
    ➜ cp <원본 파일명1> <원본 파일명2> <옮기고 싶은 디렉토리명> # 여러 파일을 한 번에 해당 디렉토리로 복사
    ➜ cp <원본 디렉토리> -r <옮기고 싶은 디렉토리명>           # 원본 디렉토리의 하위 파일까지 모두 해당 디렉토리로 복사
    ➜ cp <원본 디렉토리> -r <복사해서 만들고 싶은 디렉토리명>   # 위의 방식을 응용해서 복사해서 만들고 싶은 디렉토리 생성
    ```
    
    1. rm → 파일, 디렉토리 삭제 (rmdir)
    
    ```jsx
    ➜ rm <파일명>  			 # 해당 파일을 삭제
    ➜ rm *.txt    			 # .txt로 끝나는 모든 파일을 삭제
    ➜ rm *       		      # 전체 파일 삭제
    ➜ rm -r <파일명/디렉토리명>  # 해당 파일/디렉토리 삭제
    ➜ rm -rf <파일명/디렉토리명> # 해당 파일/디렉토리 강제 삭제(경고문구 없이 삭제)
    ```
    
    1. mkdir → 디렉토리 생성
    
    ```jsx
    ➜ mkdir <새로운 디렉토리명>  # 해당 경로에 새로운 디렉토리를 만들어줌
    ➜ mkdir -p <새로운 디렉토리명 +"/" + 새로운 하위 디렉토리명> # 하위 디렉토리까지 함께 생성
    mkdir -p dir1/subdir1      # dir1이라는 새로운 디렉토리와 그 안에 하위 디렉토리인 subdir1까지 함께 만들어줌
    ```
    
    1. pwd → 현재 디렉토리 절대 경로 반환
    
    ```jsx
    ➜ pwd
    /Users/LeeJongMin/Wecode_Project/westa
    ```
    
    1. ctrl + C / cmd + C → 현재 실행중인 프로그램 강제 종료
    2. clear : 스크립트 기록 지워줌
    3. chwon, chmod → 파일 수정시 소유자, 읽기, 쓰기 관련 문제가 생길때 파일 권한 변경
  • vim
    a.txt
    vi a.txt
    쉘에서 사용가능한 문서 편집기
    https://opentutorials.org/course/730/4561
    
    문서 수정, 저장, 확인을 위해서 모드가 세가지 있음
    
    1. 명령모드 [ESC] 
    문서 저장 :wq
    강제종료 : q!
    2. 입력 모드 → 명령모드에서 i
    yy: 커서가 위치한 행 복사 
    p: 현재 커서에 붙여 넣기, 행 복사 일 경우 아래 줄에 붙여넣음.
    3. 비주얼 모드 → 명령모드에서 v 
    문서 탐색을 편하게 하기 위한 모드임

Comment

as?

  • 타입 단언
    // 아래의 코드는 같은 기능을 함
    const name: string = 'Capt';
    const name = 'Capt' as string;
    그렇다면 일반 타입 할당이랑 다른점? 타입 단언은 타입스크립트 컴파일러보다 개발자가 더 해당 타입을 잘 알고 있을 때 사용해야 합니다. 혹은, 자바스크립트 기반 코드에 점진적으로 타입스크립트를 적용할 때도 자주 사용됩니다.
    // 예를 들어 일단 빈 객체에 타입을 Hero로 설정하고 점진적으로 수정하고 싶은 경우
    interface Hero {
      name: string;
      age: number;
    }
    
    const capt: Hero = {}; // X. 오류 발생
    capt.name = '캡틴';
    capt.age = 100;
    // 이렇게 타입 단언을 이용하면 오류가 안남
    interface Hero {
      name: string;
      age: number;
    }
    
    const capt = {} as Hero; // 오류 없음
    capt.name = '캡틴';
    capt.age = 100;
  • interface 하이브리드 타입 하이브리드 유형은 일반적으로 다음을 포함하는 다양한 유형 요소의 조합입니다.
    • 호출 가능한 속성: 객체는 함수로 호출될 수 있습니다.

    • 속성: 객체는 일반 객체처럼 속성을 가질 수 있습니다.

      interface CraftBeer {
        (beer: string): string;
        brand: string;
        brew(): void;
      }
      
      function myBeer(): CraftBeer {
      // my에서는 객체 타입으로 사용
        let my = (function(beer: string) {}) as CraftBeer;
        my.brand = 'Beer Kitchen';
        my.brew = function() {};
        return my;
      }
      // 함수로서 호출될 수 있음
      // (beer: string): string; 함수 시그니쳐가 있기 때문에 가능!
      let brewedBeer = myBeer();
      // 객체로서 매서드나 속성을 호출할 수도 있음
      brewedBeer('My First Beer');
      brewedBeer.brand = 'Pangyo Craft';
      brewedBeer.brew();

0개의 댓글