Поиск…


Синтаксис

  • Общие типы, объявленные в квадратных скобках треугольника: <T>
  • Ограничение общих типов выполняется с помощью ключевого слова extends: <T extends Car>

замечания

Общие параметры недоступны во время выполнения, они предназначены только для времени компиляции. Это означает, что вы не можете сделать что-то вроде этого:

class Executor<T, U> {
    public execute(executable: T): void {
        if (T instanceof Executable1) {    // Compilation error
            ...
        } else if (U instanceof Executable2){    // Compilation error
            ...
        }
    }
}

Однако информация о классе все еще сохраняется, поэтому вы можете проверить тип переменной, как вы всегда были в состоянии:

class Executor<T, U> {
    public execute(executable: T): void {
        if (executable instanceof Executable1) {
            ...
        } else if (executable instanceof Executable2){
            ...
        } // But in this method, since there is no parameter of type `U` it is non-sensical to ask about U's "type"
    }
}

Общие интерфейсы

Объявление общего интерфейса

interface IResult<T> {
    wasSuccessfull: boolean;
    error: T;
}

var result: IResult<string> = ....
var error: string = result.error;

Общий интерфейс с несколькими типами параметров

interface IRunnable<T, U> {
    run(input: T): U;
}

var runnable: IRunnable<string, number> = ...
var input: string;
var result: number = runnable.run(input);

Реализация универсального интерфейса

interface IResult<T>{
    wasSuccessfull: boolean;
    error: T;

    clone(): IResult<T>;
}

Реализуйте его с помощью универсального класса:

class Result<T> implements IResult<T> {
    constructor(public result: boolean, public error: T) {
    }

    public clone(): IResult<T> {
        return new Result<T>(this.result, this.error);
    }
}

Внедрите его в не общий класс:

class StringResult implements IResult<string> {
    constructor(public result: boolean, public error: string) {
    }

    public clone(): IResult<string> {
        return new StringResult(this.result, this.error);
    }
}

Общий класс

class Result<T> {
    constructor(public wasSuccessful: boolean, public error: T) {
    }

    public clone(): Result<T> {
       ...
    }
}

let r1 = new Result(false, 'error: 42');  // Compiler infers T to string
let r2 = new Result(false, 42);           // Compiler infers T to number
let r3 = new Result<string>(true, null);  // Explicitly set T to string
let r4 = new Result<string>(true, 4);     // Compilation error because 4 is not a string

Ограничения Generics

Простое ограничение:

interface IRunnable {
    run(): void;
}

interface IRunner<T extends IRunnable> {
    runSafe(runnable: T): void;
}

Более сложное ограничение:

interface IRunnble<U> {
    run(): U;
}

interface IRunner<T extends IRunnable<U>, U> {
    runSafe(runnable: T): U;
}

Еще сложнее:

interface IRunnble<V> {
    run(parameter: U): V;
}

interface IRunner<T extends IRunnable<U, V>, U, V> {
    runSafe(runnable: T, parameter: U): V;
}

Строковые ограничения типа:

interface IRunnable<T extends { run(): void }> {
    runSafe(runnable: T): void;
}

Общие функции

В интерфейсах:

interface IRunner {
    runSafe<T extends IRunnable>(runnable: T): void;
}

В классах:

class Runner implements IRunner {

    public runSafe<T extends IRunnable>(runnable: T): void {
        try {
            runnable.run();
        } catch(e) {
        }
    }

}

Простые функции:

function runSafe<T extends IRunnable>(runnable: T): void {
    try {
        runnable.run();
    } catch(e) {
    }
}

Использование общих классов и функций:

Создание экземпляра универсального класса:

var stringRunnable = new Runnable<string>();

Выполнить общую функцию:

function runSafe<T extends Runnable<U>, U>(runnable: T);

// Specify the generic types:
runSafe<Runnable<string>, string>(stringRunnable);

// Let typescript figure the generic types by himself:
runSafe(stringRunnable);

Параметры типа в качестве ограничений

С помощью TypeScript 1.8 становится возможным ограничение типа параметра ссылочными типами параметров из одного и того же списка параметров типа. Раньше это была ошибка.

 function assign<T extends U, U>(target: T, source: U): T {
    for (let id in source) {
        target[id] = source[id];
    }
    return target;
}

let x = { a: 1, b: 2, c: 3, d: 4 };
assign(x, { b: 10, d: 20 });
assign(x, { e: 0 });  // Error


Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow