[TypeScript를 기억하라고 쓰여있습니다] Generics 편.

18622 단어 TypeScript

작업 환경


이번에도 플레이그라운드로 쓰겠습니다.
TypeScript Playground

참고 자료


TypeScript Handbook

무엇이 통용됩니까


통용되는 방법과 종류에 대해 각종 유형의 기능을 연결할 수 있다.
일반적으로 TypeScript는 다음과 같은 함수를 정의합니다.
function returnValue(value: string): string {
  return value;
}
단, 이렇게 하면 매개 변수인 String형만 줄 수 있습니다.Number형과 Array형 등 다른 유형을 사용하려면 같은 함수를 여러 개 정의합니다.
여기 제넬릭스가 나왔어요.통용 전기로 아까의 것을 고쳐 보아라returnValue.
function returnValue<T>(value: T): T {
  return value;
}

let result = returnValue<number>(1);
console.log(result); // => 1

result = returnValue<string>('Hello, Generic!!');
console.log(result); // => Hello, Generic!!
함수 이름을 추가한 후<T>.이것T을 유형 매개 변수라고 하는데 매개 변수처럼 호출할 때 유형을 전달할 수 있다.
이번 예에서 모드 매개 변수도 매개 변수value와 반환 값의 데이터 형식이 된다
매개 변수로 받아들이는 형식T의value를 표시하고 반환값의 형식도 T이다.
호출 시 returnValue<string>('Hello, Generic!!'); 와 같이 <> 에서 데이터 형식을 둘러싸서 지정합니다.
※ 관례상 금형 파라미터는 자주 사용T, U, R 등입니다.

공통 및 함수


나는 너에게 더욱 복잡한 예를 하나 들어 주고 싶다.
다음과 같이 id클래스와 Post클래스가 있다고 가정합니다.
class Post {
    id: number;
    title: string;
    constructor(id: number, title: string) {
        this.id = id;
        this.title = title;
    }
}

class Category {
    id: number;
    name: string;
    constructor(id: number, name: string) {
        this.id = id;
        this.name = name;
    }
}
만약 이 두 종류의 수조가 같은 Category 수조를 가지고 있다면, id 함수를 실현하여 원소를 대체하려고 시도한다.
replace(array, newItem);
(이것은 Redux의 Reducer에서 자주 하는 처리입니다.)

일단 설치를 해 보겠습니다.


function replace<T>(data: T[], newItem: T): T[] {
    const index = data.findIndex(item => item.id === newItem.id); // Property 'id' does not exist on type 'T'.
    if (index < 0) {
        console.error(`id: ${newItem.id} not found.`); // Property 'id' does not exist on type 'T'.
        return data;
    }

    return [
      ...data.slice(0, index),
      newItem,
      ...data.slice(index + 1),
    ];
}
완성!!간단해!말하고 싶은데 오류가 생겼어요.replace(T 없음Property 'id' does not exist on type 'T'. 속성)
따라서 우리는 "idT 속성을 가지고 있다"고 제약할 것이다.

제약 유형 매개 변수 id

T 키워드 사용은 제한된다.
이 예에서 extends<T> 로 설정하면 "<T extends { id: number } 이 있는 구조(계승)"제약을 추가할 수 있습니다.
또한 예를 들어 쓰기T와 클래스 이름을 통해 유형 매개 변수{ id: number}는'<T extends MyClass>와 파생 클래스만 받아들인다'는 제약을 받을 수 있다.
그럼 아까 코드를 고쳐 쓰자.
function replace<T extends { id: number }>(data: T[], newItem: T): T[] {
    const index = data.findIndex(item => item.id === newItem.id);
    if (index < 0) {
        console.error(`id: ${newItem.id} not found.`);
        return data;
    }

    return [
      ...data.slice(0, index),
      newItem,
      ...data.slice(index + 1),
    ];
}
이게 완성이야.실제 호출 확인해 봐.

동작 확인

const postArray = [
    new Post(1, 'post1'),
    new Post(2, 'post2'),
    new Post(3, 'post3'),
    new Post(4, 'post4')
];

const categoryArray = [
    new Category(1, 'typescript'),
    new Category(2, 'coffeescript'),
    new Category(3, 'es6'),
]

const newPost = new Post(3, 'TypeScriptについて');
const newCategory = new Category(1, 'TypeScript');

let postArrayResult = replace(postArray, newPost);
console.log(postArrayResult);

let categoryArrayResult = replace(categoryArray, newCategory);
console.log(categoryArrayResult);

범용 및 클래스


클래스 이름 다음에 유형 매개 변수 T 를 추가하면 클래스에 사용할 수도 있습니다.
다음은 TypeScript Handbook 예시를 약간 수정한 것입니다.
class GenericNumber<T> {
    zeroValue: T;
    add: (x: T, y: T) => T;
    getZeroValue(): T {
        return this.zeroValue;
    }
}

let myGenericNumber = new GenericNumber<number>();
myGenericNumber.zeroValue = 0;
myGenericNumber.add = function (x, y) { return x + y; };
console.log(myGenericNumber.getZeroValue()); // => 0


let stringNumeric = new GenericNumber<string>();
stringNumeric.zeroValue = "";
stringNumeric.add = function(x, y) { return x + y; };
console.log(stringNumeric.add(stringNumeric.zeroValue, "test")); // => test
클래스에 부여된 유형 매개 변수는 이 클래스의 속성과 방법 정의에 사용할 수 있습니다.

통용 총결산

  • 함수 이름이나 클래스 이름 다음에 MyClass처럼 부여형 자변수
  • 형 매개 변수는 함수나 클래스에서 사용할 수 있다
  • 제한형 매개변수를 원하는 경우 <T> 참조<T>
  • 좋은 웹페이지 즐겨찾기