타입스크립트에서 문자열 타입은 우리가 일상적으로 사용하는 문자들의 집합을 나타냅니다. 즉, "Hello, world!", "안녕하세요", "123" 등과 같이 따옴표("") 안에 들어 있는 모든 글자들이 문자열입니다.
왜 문자열 타입이 중요할까요?
- 코드 가독성 향상: 변수의 타입을 명확히 함으로써 코드를 더 쉽게 이해하고 유지 관리할 수 있습니다.
- 오류 예방: 컴파일 시에 타입 오류를 미리 감지하여 실행 중 오류를 줄일 수 있습니다.
- 자동 완성 및 리팩토링 지원: IDE의 강력한 기능을 활용하여 개발 생산성을 높일 수 있습니다.
다양한 문자열 타입 예시
// 기본 문자열
let greeting: string = "Hello, TypeScript!";
// 빈 문자열
let emptyString: string = "";
// 숫자를 포함한 문자열
let numberString: string = "42";
// 특수 문자 포함 문자열
let specialChars: string = "Hello, world! ";
// 템플릿 문자열 (ES6+)
let name: string = "Alice";
let age: number = 30;
let templateString: string = `Hello, my name is ${name} and I am ${age} years old.`;
템플릿 문자열은 변수나 표현식을 문자열 안에 직접 삽입할 수 있는 편리한 기능입니다. 위 예시처럼 ` `(백틱)으로 감싸고, 변수나 표현식을 ${}로 감싸면 됩니다.
문자열 관련 유용한 메서드
- length: 문자열의 길이를 반환합니다.
- toUpperCase(), toLowerCase(): 문자열을 대문자 또는 소문자로 변환합니다.
- slice(): 문자열의 일부를 추출합니다.
- indexOf(): 특정 문자열이 처음으로 나타나는 인덱스를 반환합니다.
- replace(): 문자열의 특정 부분을 다른 문자열로 바꿉니다.
- split(): 문자열을 특정 기준으로 나누어 배열로 만듭니다.
let message: string = "Hello, TypeScript!";
let uppercaseMessage: string = message.toUpperCase(); // HELLO, TYPESCRIPT!
let firstWord: string = message.slice(0, 5); // Hello
문자열 타입 활용 예시
- 사용자 입력 값 검증: 사용자가 입력한 값이 문자열인지 확인하고, 필요한 형식에 맞는지 검사합니다.
- API 통신: 서버로부터 받은 JSON 데이터에서 문자열 형태의 값을 추출하여 사용합니다.
- DOM 조작: 웹 페이지의 HTML 요소의 내용을 변경하거나, 새로운 요소를 생성할 때 문자열을 사용합니다.
다양한 방식으로 표현하기
타입스크립트에서 문자열 타입을 선언하는 가장 기본적인 방법은 string 키워드를 사용하는 것입니다. 하지만 이 외에도 더욱 세밀하게 문자열 타입을 지정하고 관리할 수 있는 다양한 방법들이 있습니다.
1. 리터럴 타입 (Literal Type)
특정 문자열 값만 허용하고 싶을 때 사용합니다.
let direction: 'up' | 'down' | 'left' | 'right' = 'up';
위 예시에서는 direction 변수에 'up', 'down', 'left', 'right' 중 하나의 값만 할당할 수 있습니다.
2. 유니온 타입 (Union Type)
여러 가지 타입 중 하나를 가질 수 있도록 허용합니다. 문자열뿐만 아니라 다른 타입과의 조합도 가능합니다.
let value: string | number = 'hello';
value = 42;
3. 인터페이스 (Interface)
복잡한 객체의 구조를 정의할 때 사용하며, 문자열 타입의 프로퍼티를 가질 수 있습니다.
interface Person {
name: string;
age: number;
}
let person: Person = {
name: 'Alice',
age: 30
};
4. 타입 별칭 (Type Alias)
복잡한 타입에 간단한 이름을 부여하여 코드를 더욱 명확하게 만들 수 있습니다.
type Greeting = string;
let message: Greeting = 'Hello, world!';
5. 템플릿 문자열 타입 (Template Literal Type)
특정 패턴을 가진 문자열을 표현할 때 유용합니다.
type Email = `${string}@${string}.com`;
let email: Email = 'alice@example.com';
6. null, undefined 허용 여부
문자열에 null 또는 undefined 값을 허용할지 여부를 명시할 수 있습니다.
let nullableString: string | null = null;
let undefinedString: string | undefined = undefined;
7. readonly 키워드
문자열 값을 변경할 수 없도록 만들 때 사용합니다.
interface User {
readonly name: string;
}
선택해야 할 방법은?
- 정확한 값 제한: 리터럴 타입
- 여러 타입 허용: 유니온 타입
- 복잡한 객체: 인터페이스
- 간단한 타입 별칭: 타입 별칭
- 패턴 기반: 템플릿 문자열 타입
- null, undefined 허용: null, undefined 키워드
- 값 변경 방지: readonly 키워드
어떤 방법을 선택할지는 코드의 특성과 요구사항에 따라 달라집니다.
// 사용자 입력 값 검증
function validateInput(input: string): boolean {
return input.length > 0 && input.includes('@'); // 이메일 형식 검사
}
// API 응답 처리
interface ApiResponse {
message: string;
data: {
id: number;
name: string;
};
}
// DOM 조작
const element = document.getElementById('myElement') as HTMLInputElement;
element.value = 'Hello';
다양한 방식으로 표현하기 (심화)
이전에 문자열 타입 선언에 대해 폭넓게 다루었는데요, 이번에는 좀 더 심층적으로 다양한 방식과 활용법에 대해 알아보겠습니다.
1. enum 타입 활용
- 특정 값의 집합 표현: 특정 값들만 허용되는 경우 enum을 사용하여 코드 가독성을 높일 수 있습니다.
enum Direction {
Up = 'UP',
Down = 'DOWN',
Left = 'LEFT',
Right = 'RIGHT'
}
let direction: Direction = Direction.Up;
2. 인덱스 시그니처
- 동적 프로퍼티: 객체의 프로퍼티 이름이 동적으로 결정될 때 사용합니다.
interface StringMap {
[key: string]: string;
}
let myMap: StringMap = {
name: 'Alice',
age: '30' // 숫자를 문자열로 변환하여 저장
};
3. Mapped Type
- 기존 타입 변형: 기존 타입을 기반으로 새로운 타입을 만들 때 유용합니다.
type Readonly<T> = {
readonly [P in keyof T]: T[P];
};
interface User {
name: string;
age: number;
}
type ReadonlyUser = Readonly<User>;
4. Conditional Types
- 조건에 따른 타입: 특정 조건에 따라 다른 타입을 할당할 수 있습니다.
type IfEquals<X, Y> = (<T>() => T extends X ? 1 : 2) extends
(<T>() => T extends Y ? 1 : 2) ? true : false;
type IsString<T> = IfEquals<T, string>;
5. infer 키워드
- 제네릭 타입 추론: 함수의 인자나 반환값의 타입을 자동으로 추론합니다.
type ReturnType<T> = T extends (...args: any[]) => infer U ? U : never;
6. keyof 키워드
- 객체의 키 타입: 객체의 모든 키를 나타내는 타입을 생성합니다.
interface User {
name: string;
age: number;
}
type UserKeys = keyof User; // 'name' | 'age'
7. typeof 키워드
- 변수의 타입: 변수의 실제 타입을 가져옵니다.
let message: string = 'Hello';
type MessageType = typeof message; // string
8. indexed access types
- 인덱스 시그니처의 타입: 인덱스 시그니처를 통해 특정 프로퍼티의 타입을 추론합니다.
type UserMap = { [key: string]: { name: string; age: number } };
type UserName = UserMap[string]['name']; // string
9. mapped type 조합
- 복잡한 타입 생성: 여러 mapped type을 조합하여 다양한 타입을 만들 수 있습니다.
type Partial<T> = { [P in keyof T]?: T[P] };
10. 조건부 타입과 mapped type 조합
- 더욱 복잡한 로직: 조건부 타입과 mapped type을 함께 사용하여 강력한 타입 시스템을 구축할 수 있습니다.
언제 어떤 방식을 사용해야 할까요?
- 특정 값 제한: enum, 리터럴 타입
- 동적 프로퍼티: 인덱스 시그니처
- 기존 타입 변형: mapped type
- 조건에 따른 타입: 조건부 타입
- 제네릭 타입 추론: infer 키워드
- 객체의 키 타입: keyof 키워드
- 변수의 타입: typeof 키워드
- 인덱스 시그니처의 타입: indexed access types
- 복잡한 타입 생성: mapped type 조합
'웹개발 > typescript' 카테고리의 다른 글
[타입스크립트] 튜플 타입 (0) | 2024.08.30 |
---|---|
[타입스크립트] 함수 타입 (0) | 2024.08.30 |
[타입스크립트] any 타입 / unknown 타입 (0) | 2024.08.30 |
[타입스크립트] 배열 타입 (2) | 2024.08.30 |
[타입스크립트] null과 undefined (0) | 2024.08.30 |