사용할 제네릭(generic) 클래스의 기본 구조

Map<k,v>

 

type RoutineExerciseItemDto = {
  exerciseName: string;
  bodyPart: string;
};

type RoutineData = {
  id: number;
  name: string;
  routine: RoutineExerciseItemDto[];
};

const expampleMap = new Map<number, RoutineData>();

routineMap.set(1, {
  id: 101,
  name: "Chest Day",
  routine: [/* RoutineExerciseItemDto 객체들 */]
});

-> 1 이 key 가되고 {} 가 value 가 된다.

 

위의 exampleMap을 이용하여 파이썬의 딕션너리와 비슷하게  만들어보기 

const routines = [
  {
    id: 101,
    name: "Chest Day",
    exercises: [
      { exerciseName: "Bench Press", bodyPart: "Chest" },
      { exerciseName: "Push-up", bodyPart: "Chest" },
    ],
  },
  {
    id: 102,
    name: "Leg Day",
    exercises: [
      { exerciseName: "Squat", bodyPart: "Legs" },
      { exerciseName: "Lunge", bodyPart: "Legs" },
    ],
  },
  {
    id: 103,
    name: "Back Day",
    exercises: [
      { exerciseName: "Deadlift", bodyPart: "Back" },
      { exerciseName: "Pull-up", bodyPart: "Back" },
    ],
  }
];

// 루프를 이용한 Map 초기화
routines.forEach((routine, index) => {
  routineMap.set(index + 1, {
    id: routine.id,
    name: routine.name,
    stationary: routine.exercises,
  });
});

 

 

각 key 에 해당하는 값 불러오기

routineMap.get(1);
//  반환 값
// {
//   id: 101,
//   name: "Chest Day",
//   stationary: [...]
// }

Index signature 란

객체의 속성(property)에 동적인 키를 사용하여 자유롭게 구현할 수 있도록 도와주는 TypeScript의  문법이다.

 

구문 (Syntax)

{ [key: KeyType]: ValueType }

- [ ] 안에 key 의 타입을 설정

- key : 객체의 속성을 나타내는 이름

- KeyType : key 의 타입,  주로 string, number 을 사용

- ValueType : 각 키에 해당하는 값의 타입

 

장점

  1. 유연성: 사전에 정의되지 않은 키를 다룰 수 있다.
  2. 타입 안전성: 객체의 키와 값에 대한 타입을 지정하여 타입 안전성을 유지한다.
  3. 동적 데이터 처리: 동적인 데이터 구조를 처리하는 데 유용합니다. 예를 들어, 외부 API로부터 동적으로 키가 결정되는 데이터를 받을 때 유용하다.

단점

  1. 데이터 타입의 유연성 부족 : 객체 내에 다양한 타입의 값을 혼합해서 사용할 수 없다
  2. 유지보수성 감소 : 동적인 속성 이름을 사용하기 때문에, 객체의 구조를 한눈에 파악하기 어렵고, 추후에 구조를 변경하거나 디버깅할 때 어려움이 있을 수 있다.

예제

  • string 타입의 키
interface StringIndexSignature {
  [key: string]: number;
}

const example: StringIndexSignature = {};
example['one'] = 1;
example['two'] = 2;

console.log(example); // { one: 1, two: 2 }
  • number 타입의 키
interface NumberIndexSignature {
  [key: number]: string;
}

const example: NumberIndexSignature = {};
example[1] = 'one';
example[2] = 'two';

console.log(example); // { 1: 'one', 2: 'two' }
  • DTO 에 string 타입의 키 적용
interface AnimalDataDTO {
  [animal: string]: number;
}

export class ExampleDTO {
  animal: YearlyDataDTO;

  constructor() {
    this.animal = {};
  }
}

const example: ExampleDTO = new ExampleDTO();
example['tiger'] = 1
console.log(example) // { tiger: 1 }

만들고 싶은 데이터 구조

{
  'year' : { 
    '2023' : { 'Back' : [ 10, 30, 40, ,,,],...}, 
    '2024' : { ...}
  }
}

 

 

타입을 정의하여 구현 하기

// TypeScript에서 객체의 키와 값이 동적으로 설정될 수 있도록 문법
// index signiture 를 이용
class ExerciseDataDTO {
  [bodyPart: string]: number[];
}

class YearlyDataDTO {
  [year: number]: ExerciseDataDTO;
}


export class AggregatedResultDTO {
  year: YearlyDataDTO;

  constructor() {
    this.year = {};
  }
}

https://joey0203.tistory.com/369 에서 내용 추가.

 

장점

  • 객체가 변경되지 않으므로 예측가능한 상태 유지 가능
  • 이해하기 쉽고 안정적인 서비스 개발에 도움이 된다.

 

단점

  • 객체의 값이 할당될 때마다 새로운 객체가 필요하다.

 

구현 방법

const 사용

const helloWorld = "Hello World";

helloWorld = "Hi world"; // Cannot assign to 'helloWorld' because it is a constant.

 

Object.freez() 이용

const myDefinitelyConstantObject = Object.freeze({
  msg: "Hello World",
});

// Cannot assign to 'msg' because it is a read-only property.
myDefinitelyConstantObject.msg = "Hi"


const myFrozenArray = Object.freeze(["Hi"]);

//Property 'push' does not exist on type 'readonly string[]'.
myFrozenArray.push("World");

 

readonly 이용

class UserDetails { 
        readonly name: string 
        readonly city: string 
        readonly phoneNo: number 
        constructor(name: string, city: string, phoneNo: number){ 
            this.name = name 
            this.city = city 
            this.phoneNo = phoneNo 
        }   
} 
      
const user1 = new UserDetails("ABCD", "XYZ", 1234567890); 
const user2 = new UserDetails("APPLE", "PQR", 1269785100);

 

 

 

 

참고자료

'프로그래밍 > TypeScript' 카테고리의 다른 글

[TS] index signature  (0) 2024.08.03
[ TS ] DTO object 구현  (0) 2024.08.03
[ TS ] 비밀번호 암호화 (bcypt)  (0) 2024.06.13
[ TS ] tsconfig.json 의 내용 정리  (0) 2024.06.08
[ TS ] 오버로딩  (1) 2024.05.09

 

 

라이브러리 설치

$ npm i bcrypt
$ npm i -D @types/bcrypt

 

비밀번호 암호화하기

  async signUp(signUpRequestDto: SignUpRequestDto) {
    const { email, password } = signUpRequestDto;
    const user = new User();
    user.email = email;
    const hashedPassword = await bcrypt.hash(password, 10);
    user.password = hashedPassword;
    return await this.userRepository.save(user);
  }

 

saltround 를 .env 파일에서 호출하여 넣을 때

호출한 값의 데이터 타입 = string 이므로 아래와 같이 확인 절차를 걸쳐서 number 로 변환해주어야 한다.

const saltRounds = this.configService.get<string>('SALT_ROUNDS');
if (saltRounds === undefined) {
    throw new Error('SALT_ROUNDS is not defined in the configuration.');
}
const hashedPassword = await bcrypt.hash(password, parseInt(saltRounds));

 

 

signIn 을 할때는  아래 코드를 이용하여 입력된 패스워드와 DB에 저장된 패스워드가 일치하는지 확인

const passwordMatch = await bcrypt.compare(password, user.password);

 

 

자료출처

https://docs.nestjs.com/security/encryption-and-hashing

 

'프로그래밍 > TypeScript' 카테고리의 다른 글

[ TS ] DTO object 구현  (0) 2024.08.03
[ TS ] 불변객체 immutable 장점 / 단점 / 구현방법  (0) 2024.07.28
[ TS ] tsconfig.json 의 내용 정리  (0) 2024.06.08
[ TS ] 오버로딩  (1) 2024.05.09
[ TS ] Promise<void> 의미  (0) 2024.05.07

+ Recent posts