TypeScript - Learning TypeScript Chap. 6 Array

이소라·2023년 3월 30일
0

TypeScript

목록 보기
20/28

6. Arrays

  • JavaScript에서 배열은 내부에 모든 타입의 값을 혼합해서 저장할 수 있습니다.
const elements = [true, null, undefined, 42];

elements.push('even', ['more']);
  • TypeScript는 초기 배열에 어떤 데이터 타입이 있는지 기억하고, 배열이 해당 데이터 타입에서만 작동하도록 제한합니다.
    • 이런 방식으로 배열의 데이터 타입을 하나로 유지시킵니다.
// warriors: string[]
const warriors = ['AAA', 'BBB'];
// Ok
warriors.push('CCC');
// Error: Argument of type 'boolean' is not assignable to parameter of type 'string'
warriors.push(true);

6.1 Array Types

  • TypeScript는 변수에 type annotation을 제공해 배열이 포함해야 하는 값의 타입을 알려주려고 합니다.
  • 배열에 대한 typee annotation은 배열의 요소 타입 다음에 []가 와야 합니다.
let arrayOfNumbers : number[];
arrayOfNumbers = [1, 2, 3, 4, 5];

6.1.1 Array and Function Types

  • 배열 타입은 함수 타입에 무엇이 있는지를 구별하는 괄호가 필요한 구문 컨테이너의 예입니다.
  • 괄호는 annotation의 어느 부분이 함수 반환 부분이고 어느 부분이 배열 타입 묶음인지를 나타내기 위해 사용합니다.
// 타입 : string 배열을 반환하는 함수
let createStrings: () => string;
// 타입 : string을 반환하는 함수들의 배열
let stringCreators: (() => string)[];

6.1.2 Union-Type Arrays

  • TypeScript에서 두 가지 이상의 요소 타입이 포함된 배열을 선언할 때 union 타입을 사용합니다.
  • union 타입으로 배열 타입을 선언할 때, annotation의 어느 부분이 배열 요소이고 어느 부분이 union 타입 묶음인지를 나타내기 위해 괄호를 사용합니다.
// 타입 : string 또는 number의 배열
let stringOrArrayOfNumbers: string | number[];
// 타입 : 각각 string 또는 number인 요소의 배열
let arrayOfStringOrNumbers: (string | number)[];
  • union 타입 배열의 요소 타입은 배열에 담긴 요소에 대한 모든 가능한 타입의 집합입니다.
// alphabetMaybe: (string | undefined)[]
const alphabetMaybe = ['A', 'B', undefined];

6.1.3 Evolving Any Arrays

  • 초기에 빈 배열로 설정된 변수에 type annotation을 포함하지 않으면, TypeScript는 배열을 any[]로 취급하고 모든 타입의 값을 받을 수 있습니다.
// values: any[]
let values = [];
// values: string[]
values.push('');
// values: (number | string)[]
values[0] = 0;
  • 배열이 any 타입이 되도록 허용하거나 일반적으로 any 타입을 사용하도록 허용하면 TypeScript 검사 목적을 부분적으로 무효화합니다.
    • TypeScript는 값의 타입을 알 때 가장 잘 작동합니다.

6.1.4 Mutidimensional Arrays

  • 2차원 배열 또는 배열의 배열은 두 개의 대괄호([][])를 갖습니다.
let arrayOfArrayOfNumbers: number[][];

arrayOfArrayOfNumbers = [
  [1, 2, 3],
  [4, 5, 6],
  [7, 8, 9]
];
  • n차원 배열 타입에는 n개의 []가 있습니다.

  • Type[][]와 (Type[])[]는 같은 타입입니다.

// arrayOfArrayOfNumbers: number[][]
let arrayOfArrayOfNumbers: (number[])[]



6.2 Array Members

  • TypeScript는 인덱스를 기반으로 배열의 멤버를 찾아서 해당 배열의 타입 요소를 되돌려줍니다.
const defenders = ['AAA', 'BBB'];
// defender: string
const defender = defenders[0];
  • union 타입으로 된 배열의 멤버는 동일한 union 타입입니다.
const soldiersOrDates = ['AAA', new Date(1782, 6, 3)];
// soldierOrDate: string | Date
const soldierOrDate = soldiersOrDates[0];

6.2.1 Caveat: Unsound Members

  • TypeScript의 타입 시스템은 기술적으로 불안정하다고 알려져 있습니다.
    • 특히 배열은 타입 시스템에서 불안정한 소스입니다.
  • TypeScript는 모든 배열의 멤버에 대한 접근이 해당 배열의 멤버를 반환한다고 가정합니다.
    • 반면에 JavaScript에서는 배열의 길이보다 큰 인덱스로 배열 요소에 접근하면 undefined를 제공합니다.
function withElements(elements: string[]) {
  console.log(elements[9001].length); // Error 없음
}
withElements(['a', 'b']); // 런타임에서 Cannot read property 'length' of undefined' Error 발생함
  • TypeScript에는 배열 조회를 더 제한하고 타입을 안전하게 만드는 noUncheckedIndexedAccess 플래그가 있습니다.
    • 그러나 이 플래그는 매우 엄격해서 대부분의 프로젝트에서 사용하지 않습니다.



6.3 Spreads and Rests

  • TypeScript에서 나머지 매개변수와 배열 스프레드 모두 이해합니다.

6.3.1 Spreads

  • 서로 다른 타입의 두 배열을 함께 스프레드하여 새 배열을 생성했을 때, 새 배열을 두 개의 원래 타입 중 어느 하나의 요소인 union 타입 배열로 이해합니다.
// soldiers: string[]
const soldiers = ['AAA', 'BBB', 'CCC'];
// soldierAges: number[]
const soldierAges = [21, 31, 41];
// conjoined: (string | number)[]
const conjoined = [...soldiers, ...soldierAges];

6.3.2 Spreading Rest Parameters

  • TypeScript는 나머지 매개변수로 배열을 스프레드하는 JavaScript 실행을 인식하고 이에 대해 타입 검사를 수행합니다.
    • 나머지 매개 변수를 위한 인수로 사용되는 배열은 나머지 매개변수와 동일한 배열 타입을 가져야 합니다.
function logWarriors(greeting: string, ...names: string[]) {
  for (const name of names) {
    console.log(`${greeting}, ${name}`);
  }
}
const warriors = ['AAA', 'BBB', 'CCC'];
// Ok
logWarriors('hello', warrior);

const birthYears = [1999, 1888, 1777];
// Error: Argument of type 'number' is not assignable to parameter of type 'string'
logWarriors('born in', birthYears);



6.4 Tuples

  • 고정된 크기의 배열을 튜플이라고 합니다.
  • 튜플은 각 인덱스에 알려진 특정한 타입을 가집니다.
  • 튜플은 type annotation에서 괄호 안에 요소의 값 대신 타입을 적습니다.
let YearAndWarrior: [number, string];
// Ok
yearAndWarrior = [1999, 'AA'];
// Error: Type '[number]' is not assignable to type '[number, string]'
yearAndWarriro = [1000]
  • 한 번에 여러 값을 할당하기 위해 튜플과 배열 구조 분해 할당을 함께 자주 사용합니다.
// year: number
// warrior: string
let [year, warrior] = Math.random() > 0.5 ? [1999, 'AA'] : [1000, 'BB'];

6.4.1 Tuple Assignability

  • TypeScript에서 튜플 타입은 가변 길이의 배열 타입보다 더 구체적으로 처리됩니다.
    • 가변 길이의 배열 타입은 튜플 타입에 할당할 수 없습니다.
// pairLoose: (boolean | number)[]
const pairLoose = [false, 123];
// Error: Type '(boolean | number)[]' is not assignable to type '[boolean, number]'
//	Target requires 2 elements but source may have fewer
const pairTupleLoose: [boolean, number] = pairLoose;
  • TypeScript에서 길이가 다른 튜플은 서로 할당할 수 없습니다.
const tupleThree: [boolean, number, string] = [false, 123, 'AAA'];

const tupleTwo: [boolean, number] = [tupleThree[0], tupleThree[1]];
// Error: Type '[boolean, number, string]' is not assignable to type '[boolean, number]'
//	Source has 3 elements but target allows only 2
const tupleTwoExtra: [boolean, number] = tupleThree;

  • 튜플은 구체적인 길이와 요소 타입 정보를 가지는 배열로 간주되므로 함수에 전달할 인수를 저장하는 데 특히 유용합니다.
  • TypeScript는 나머지 매개변수로 전달된 튜플에 정확한 타입 검사를 제공할 수 있습니다.
function logPair(name: string, value: number) {
  console.log(`${name} has ${value}`);
}

const pairArray = ['A', 1];
// Error: A spread argument must either have a tuple type or be passed to a rest parameter
logPair(...pairArray);

const pairTupleIncorrect: [number, string] = [1, 'A'];
// Error: Argument of type 'number' is not assignable to parameter of type 'string'
logPair(...pairTupleIncorrect);

const pairTupleCorrect: [string, number] = ['A', 1];
// Ok
logPair(...pairTupleCorrect);

6.4.2 Tuple Inferences

  • TypeScripts는 생성된 배열을 튜플이 아닌 가변 길이의 배열로 취급합니다.
    • 배열이 변수의 초기값 또는 반환값으로 사용될 때, 가변 길이의 배열로 가정합니다.
function firstCharAndSize(input: string) {
  // (string | number)[]
  return [input[0], input.length];
}
// firstChar: string | number
// size: string | number
const [firstChar, size] = firstCharSize('Gudit');
  • 함수의 반환 타입 annotation에 튜플 타입을 사용할 수 있습니다.
function firstCharAndSizeExciplit(input: string): [string, number] {
  // [string | number]
  return [input[0], input.length];
}
// firstChar: string
// size: number
const [firstChar, size] = firstCharSizeExciplit('Gudit');

  • TypeScript는 값 뒤에 넣을 수 있는 const assertion인 as const 연산자를 제공합니다.
    • const assertion은 TypeScript가 타입을 유추할 때 읽기 전용이 가능한 값 형식을 사용하도록 지시합니다.
    • 배열 리터럴 뒤에 as const가 배치되면 배열을 튜플로 처리되어야 함을 나타냅니다.
// unionArray: (number | string)[]
const unionArray = [1157, 'aaa'];
// readonlyTuple: readonly [1157, 'aaa']
const readonlyTuple = [1157, 'aaa'] as const;
  • const assertion은 해당 튜플이 읽기 전용이고 값 수정이 예상되는 곳에서 사용할 수 없음을 나타냅니다.
const pairMutable: [number, string] = [1157, 'aaa'];
// Ok
pairMutable[0] = 1111;
// Error: The type 'readonly [1157, "aaa"]' is readonly 
// 	and cannot assigned to the mutable type '[number, string]'  
const pairAlsoMutable: [number, string] = [1157, 'aaa'] as const;

const pairConst = [1157, 'aaa'] as const;
// Error: Cannot assign to '0' because it is a read-only property
pairConst[0] = 1111;
  • 읽기 전용 튜플은 함수 반환에 편리합니다.
function firstCharAndSizeAsConst(input: string) {
  // readonly [string , number]
  return [input[0], input.length] as const;
}
// firstChar: string
// size: number
const [firstChar, size] = firstCharSizeExciplit('Gudit');



0개의 댓글