TIL

2024.03.04 TIL #typeScript 기본 type 종류

inz1234 2024. 3. 4. 21:00

>> 기본타입


1. boolean : 2가지의 상태를 표현
[예시]
function isValidPassword(password: string): boolean {
  return password.length >= 8;
}

const password = "q1w2e3r4!";
const valid = isValidPassword(password);
if (valid) {
  console.log("유효한 패스워드입니다!");
} else {
  console.log("유효하지 않은 패스워드입니다!");
}
+) 3가지 이상의 상태를 표현할 때: enum or string


2. number
- typeScript에서 숫자는 정수, 실수, 진수까지 포함
[예시]
function calculateArea(radius: number): number {
  return Math.PI * radius * radius;
}
// pi(무리수)도 number로 가능

const radius = 5;
const area = calculateArea(radius);
console.log(`반지름이 ${radius}인 원의 넓이: ${area}`);


3. string
[예시]
function greet(name: string): string {
  return `안녕, ${name}!`;
}

const name = "Spartan";
const greeting = greet(name);
console.log(greeting);


4. 배열
[예시]
function calculateSum(numbers: number[]): number {
  let sum: number = 0;
  for (let i = 0; i < numbers.length; i++) {
    sum += numbers[i];
  }
  return sum;
}

const testScores: number[] = [90, 85, 78, 92, 88];
const sumScore = calculateSum(testScores);
console.log(`점수의 총합: ${sumScore}`);


5. 튜플
- 서로 다른 타입의 원소를 순서에 맞게 가질 수 있는 특수형태 타입
- const testScores: number[] = [90, 85, 78, 92, “88”];  // 이렇게 숫자 배열에 문자열 "88"을 넣으면 원래 error 발생
- 튜플은 내가 어떤 타입의 원소를 허용할 것인지 정의만 해주면 됨!
[예시]
const person: [string, number, boolean] = ['Spartan', 25, false];
const person2: [string, number, boolean] = [25, 'Spartan', false]; // 오류!
+) 튜플에 push를 써서 추가저장할 수 있나요? 되긴 됩니다. But 좋지 않으니 그렇게 하지 마세요.


6. enum
- 열거형 데이터 타입
- 다양한 "상수"를 이해하기 쉬운 "문자열" 이름으로 접근하고 사용할 수 있게 하는 타입
=> 명확하게 "관련된 상수들"을 그룹화하고자 할 때 유용 
     그러나 값의 수가 많지 않고, 값들 사이의 관계가 뚜렷하지 않으면 사용하지 않는 게 나음
- enum의 각 요소의 값이 설정되어 있지 않으면 기본적으로 숫자 0부터 시작
- enum의 각 요소의 type은 number or string 값만 할당 가능
[예시]
enum UserRole {
  ADMIN = "ADMIN",
  EDITOR = "EDITOR",
  USER = "USER",
}

enum UserLevel {
  NOT_OPERATOR, // 0  => 값을 설정하지 않으면 자연스럽게 앞에 있는애는 0, 두번째는 1이 됨
  OPERATOR // 1
}

function checkPermission(userRole: UserRole, userLevel: UserLevel): void {
  if (userLevel === UserLevel.NOT_OPERATOR) {  

   // user.Level === 0 이랑 똑같은 말 hard 코딩을 막기 위해 변수로 ㅇㅇ
    console.log('당신은 일반 사용자 레벨이에요');
  } else {
    console.log('당신은 운영자 레벨이군요');
  } 

  if (userRole === UserRole.ADMIN) {
    console.log("당신은 어드민이군요");
  } else if (userRole === UserRole.EDITOR) {
    console.log("당신은 에디터에요");
  } else {
    console.log("당신은 사용자군요");
  }
}

const userRole: UserRole = UserRole.EDITOR;
const userLevel: UserLevel = UserLevel.NOT_OPERATOR;
checkPermission(userRole, userLevel); //  "당신은 일반 사용자 레벨이에요" "당신은 에디터에요"


7. const & readonly
- 불변성을 보장하는 친구
readonly
- typeScript에서 등장
- 객체의 속성을 불변으로 만드는 데 사용되는 키워드 = 클래스나 인터페이스의 속성을 변경할 수 없게 만듦
[예시]
class Person {                // 클래스는 다른 강의에서 자세히 설명해드릴게요!
  readonly name: string;  // Person: 속성이 name과 age라는 객체

                                   -> constructor에서만 초기화 가능 그 뒤에는 수정, 바꿀 수 없음 =  배열일 경우 push 안됨
  readonly age: number;
  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }
}

const person = new Person('Spartan', 30);

console.log(person.name);  // 출력: 'Spartan'
console.log(person.age);   // 출력: 30

person.name = 'Jane';      // 에러: 'name'은 readonly 속성이므로 다시 할당할 수 없어요!
person.age = 25;           // 에러: 'age'은 readonly 속성이므로 다시 할당할 수 없어요!

+) readonly를 const로 치환하면 어케돼요?
=> error // const 키워드는 일반변수를 상수화할 때 사용


8. any
- 모든 타입의 슈퍼타입!!
- 아주 위험한 친구
- 가급적 사용 X
[예시]
let anything: any;
anything = 5;                             // 최초에는 숫자를 넣었지만
anything = 'Hello';                       // 문자열도 들어가고요
anything = { id: 1, name: 'John' };    // JSON도 들어가네요


9. unknown
- any와 비슷하지만, 좀 더 안전
- 얘도 모든 타입의 값 저장가능
- But, unknown 타입의 값을 다른 타입의 변수에 할당하려면 unknown value의 타입을 정확히 명시해줘야함

[예시1] : 타입단언! => 더 선호됨
let unknownValue: unknown = '나는 문자열이지롱!';  
console.log(unknownValue);                  // 나는 문자열이지롱!

let stringValue: string;
stringValue = unknownValue;               // 에러 발생 => unknownValue가 언뜻 보기에는 string 같지만,

                                                       정확히 명시를 해줘야 함! 넌 string이야!!
stringValue = unknownValue as string;   // 이렇게 그래야 다른 변수에 할당 가능!
console.log(stringValue);                     // 나는 문자열이지롱! 그래야 정상적으로 출력됨

[예시2] : typeOf로 다른 변수에 unknown을 할당하기 전에 type 체크를 먼저 하고 할당
let unknownValue: unknown = '나는 문자열이지롱!';
let stringValue: string;

if (typeof unknownValue === 'string') {
  stringValue = unknownValue;
  console.log('unknownValue는 문자열이네요~');
} else {
  console.log('unknownValue는 문자열이 아니었습니다~');
}


10. union
- unknown이 any 보다는 안전성을 보장하지만, unknown 타입도 결국 타입을 명시해주고 재할당이 이루어지지 않으면 안정성 보장 안됨ㅠ
- 이럴 때 union type : 대충 보고 어떤 타입이 들어오겠다 각이 나오면, 그 타입을 가질 수 있는 변수를 선언할 때 사용
- 얘도 되고, 쟤도 되고~ => | 연산자로 여러 타입 결합

[예시]
type StringOrNumber = string | number;             // string도 될 수 있고~ number도 될 수 있고~ 

                                                                    원한다면 | boolean 이런식으로 타입 추가가 가능해요!

function processValue(value: StringOrNumber) {   // value로 들어올 인자의 타입은 string이 될 수도~ number도 될 수도
  if (typeof value === 'string') {                         // 그래서 만약 string이면~
    // value는 여기서 string 타입으로 간주됩니다.
    console.log('String value:', value);                  // 얘를 출력하고
  } else if (typeof value === 'number') {              // number면
    // value는 여기서 number 타입으로 간주되구요!
    console.log('Number value:', value);               // 얘를 출력하고~
  }
}

processValue('Hello');                                       // 얘는 'String value:' 'Hello' 가 나올 것이고
processValue(42);                                            // 얘는 'Number value:' 42 가 나올 것이고


* 가변적 타입의 데이터를 저장해야할 때 => any 말고 unknown이 나음
* 가변적 타입을 일일이 정의할 수 있다면 => union type이 가장 나음