Подтвердить что ты не робот

Какая разница между общим ключом (T) и любым в typescript

В чем разница между generic key (T) vs any в typescript?

Функция 1

function identity(arg: any): any {
    return arg;
}

Функция 2 и 3

function identity<T>(arg: T): T {
    return arg;
}

function identity<T>(arg: T[]): T[] {
    return arg;
}

Функция 1 и 3 принимает, если мы передаем любой тип data type, но функция 2 не принимает, если мы пройдем array. общий метод означает, что он принимает все типы данных во время компиляции. но вот почему нам нужно объявить array в общем методе?

Также какая функция хороша для производительности (функция 1 или функция 3)?

4b9b3361

Ответ 1

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

const foo: any = fn(['whatever']);

И есть разница для типизированного кода:

const foo: string = fn('ok');
const bar: string = fn([{ not: 'ok' }]);

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

function fn(arg: any): any { ... }

Эта сигнатура предполагает, что функция возвращает тот же тип, что и аргумент:

function fn<T>(arg: T): T { ... }

Реальные функции обычно более значимы, чем просто return arg пример. Общий тип может получить преимущества от ограничений типа (в то время как any, очевидно, не может):

function fn<T>(arg: T[]): T[] {
  return arg.map((v, i) => arg[i - 1]);
}

Но преимущества становятся более очевидными, когда функция используется в сочетании с другими родовыми классами и универсальными функциями (и устраняется, если задействованы не-генерики):

function fn<T>(arg: T[]): T[] {
  return Array.from(new Set<T>(arg));
}

Это позволяет последовательно поддерживать тип T между вводом (аргументом) и выходом (возвращаемым значением):

const foo: string[] = fn(['ok']);
const bar: string[] = fn([{ not: 'ok' }]);

Не может быть никакой разницы в производительности, поскольку типы TypeScript существуют только во время разработки.

Ответ 2

При использовании любого из этих методов нет никакой разницы в производительности, потому что все эти фантазии - это всего лишь Typescript сахара и предназначены только для разработки.

Вся проверка типов выполняется только во время компиляции (когда Typescript переводит/преобразует ваш код обратно в обычный javascript на вашем сервере).

В любом случае, когда ваш код отправляется в пользовательский браузер, это выглядит так:

function identity(arg){
    return arg;
}

Но для объяснения различий:

При использовании any вы потеряете все проверки типов и проверку безопасности, предлагаемые Typescript, тогда как T ведет себя как переменная, которая будет удерживать тип, который вы не знаете, что он собирается быть.

So

function identity<T>(arg: T): T {
    return arg;
}

В приведенном выше примере мы знаем, что если identify принимает number, он вернет number и т.д., где as:


function identity(arg: any): any {
    return arg;
}

Но теперь вы не знаете, являются ли теги arg и returned одним и тем же типом.


Другая проблема, которую будет решать T, - это когда вы создаете метод внутри класса и ожидаете аргумент, который вы хотите удостовериться, что этот метод будет принимать аргументы только с тем же типом аргумента конструктора класса при создании экземпляра.

export class MyClass<T>{

   myMethod(anotherArg:T){}

}

Итак, используя выше:

let str = "string";
let instance = new MyClass(str);
instance.myMethod("other string") // will compile

Где как:

let num = 32423423;
let instance = new MyClass(num);
instance.myMethod("other string") // won't compile

Ответ 3

Все время any во время выполнения, а поверх этого оно any во время компиляции в JavaScript. Вот почему TypeScript обеспечивает безопасность типов во время компиляции.

Разница между any и T/T extends и т.д. заключается в том, что у вас есть безопасность типа во время компиляции, например

protected typeSafety = <T extends String>(args:T):T =>{
    return args;
}

this.typeSafety(1); // compile error
this.typeSafety("string"); // good to go

Если функция принимает что-либо, у вас будет ошибка во время выполнения, которая будет слишком поздней.

Ответ 4

Основное использование T заключается в том, чтобы избежать нарушения типа при вызове метода.

Пример:

Если вы выполните:

let foo = new Foo();
identity(foo).bar();

Вторая строка будет в порядке для компилятора, но не потому, что он знает, что bar существует в типе Foo, потому что он any и any может иметь любой метод.

Если вы выполните:

let foo = new Foo();
identity<Foo>(foo).bar();
identity<Foo>(foo).notExistingMethod();

Вторая строка будет компилироваться отлично, а не третья, потому что Foo не имеет метода notExistingMethod.

любой часто используется, когда вам нужно создать что-то более чем в Javascript-способе, что означает, что вы действительно не знаете, что находится в вашем объекте, поскольку Javascript не имеет каких-либо типов (я не говорю о es6 ofc).