frontend-interview icon indicating copy to clipboard operation
frontend-interview copied to clipboard

TS中的泛型是什么应用场景

Open su37josephxia opened this issue 2 years ago • 7 comments

su37josephxia avatar Mar 07 '22 00:03 su37josephxia

泛型

泛型(Generics)是指在定义函数、接口或类的时候,不预先指定具体的类型,而在使用的时候在指定类型的一种特性

多个类型参数

function swap<T, U>(tuple: [T, U]): [U, T] {
  return [tuple[1], tuple[0]];
}

swap([7, "seven"]); // ['seven', 7]

泛型约束

interface Lengthwise {
  length: number;
}

function loggingIdentity<T extends Lengthwise>(arg: T): T {
  console.log(arg.length);
  return arg;
}

泛型接口

interface Cart<T> {
  list: T[];
}
let cart: Cart<{ name: string; price: number }> = {
  list: [{ name: "hello", price: 10 }],
};
console.log(cart.list[0].name, cart.list[0].price);

泛型类

class MyArray<T> {
  private list: T[] = [];
  add(value: T) {
    this.list.push(value);
  }
  getMax(): T {
    let result = this.list[0];
    for (let i = 0; i < this.list.length; i++) {
      if (this.list[i] > result) {
        result = this.list[i];
      }
    }
    return result;
  }
}
let arr = new MyArray();
arr.add(1);
arr.add(2);
arr.add(3);
let ret = arr.getMax();
console.log(ret);

泛型类型别名

type Cart<T> = { list: T[] } | T[];
let c1: Cart<string> = { list: ["1"] };
let c2: Cart<number> = [1];

泛型参数的默认类型

function createArray<T = string>(length: number, value: T): Array<T> {
  let result: T[] = [];
  for (let i = 0; i < length; i++) {
    result[i] = value;
  }
  return result;
}

7TingYu avatar Mar 09 '22 09:03 7TingYu

TS中的泛型是什么应用场景

泛型(Generics)是指在定义函数、接口或类的时候,不预先指定具体的类型,而在使用的时候再指定类型的一种特性。

型的语法是 <> 里写类型参数,一般可以用 T 来表示

  • 处理函数参数:做到输入和输出的类型统一

    function print<T>(arg:T):T {
        console.log(arg)
        return arg
    }
    
  • 泛型约束:在函数内部使用泛型变量的时候,由于事先不知道它是哪种类型,所以不能随意的操作它的属性或方法,此时可以对泛型进行约束,只允许这个函数传入那些包含 length 属性的变量。使用关键字extends

  • 泛型接口:用接口的方式定义一个函数需要符合的形状

  • 泛型类、泛型参数的默认类型

泛型体现了一种面向对象的思想

frllk avatar Mar 09 '22 15:03 frllk

泛型的本质是参数化类型,就是所操作的数据类型被指定为一个参数,这种参数类型可以用在类、接口和方法的创建中,分别成为泛型类,泛型接口、泛型方法。

为什么使用泛型 TypeScript 中不建议使用 any 类型,不能保证类型安全,调试时缺乏完整的信息。

TypeScript可以使用泛型来创建可重用的组件。支持当前数据类型,同时也能支持未来的数据类型。扩展灵活。可以在编译时发现你的类型错误,从而保证了类型安全。

泛型的使用 使用泛型可以创建泛型函数、泛型接口,泛型类

partiallove avatar Mar 09 '22 15:03 partiallove

TS中的泛型是什么应用场景?

泛型函数:可以适用于多个类型,同时又能够保证参数类型与返回值的类型一致

// 类型变量T —— T帮助捕获传入的类型
function identity<T>(arg: T): T {
        return arg;
}

泛型函数的使用: 传入所有的参数,包含类型参数 let output = identity("myString") 编译器会根据传入的参数自动地帮助我们确定T的类型 let output = identity("myString") 编译器可以查看myString的值,然后把T设置为它的类型

泛型变量: 把泛型变量T当做类型的一部分使用,而不是整个类型,增加了灵活性

//  返回元素类型是T的数组
function loggingIdentity<T>(arg: T[]): T[] {
    console.log(arg.length);  
    return arg;
}

泛型类型:<T> 泛型接口:

interface GenericIdentityFn {
    <T>(arg: T): T;
}

类有两部分:静态部分和实例部分。 泛型类指的是实例部分的类型,所以类的静态属性不能使用这个泛型类型 泛型类:泛型类型放在类后面,可以帮助我们确认类的所有属性都在使用相同的类型 泛型约束:定义一个接口来描述约束条件。 创建一个包含 .length属性的接口,使用这个接口和extends关键字来实现约束

// 接口 interface Lengthwise { length: number; } // 泛型约束 function loggingIdentity<T extends Lengthwise>(arg: T): T { console.log(arg.length); // Now we know it has a .length property, so no more error return arg; }

ruixue0702 avatar Mar 09 '22 15:03 ruixue0702

泛型

泛型的本质是参数化类型,通俗的讲就是所操作的数据类型被指定为一个参数,这种参数类型可以用在类、接口和方法的创建中,分别成为泛型类,泛型接口、泛型方法。 TypeScript 可以使用泛型来创建可重用的组件。支持当前数据类型,同时也能支持未来的数据类型。扩展灵活。可以在编译时发现你的类型错误,从而保证了类型安全。

  function identity<T>(arg:T): T {
    console.log(typeof arg)
    return arg
  }
  let output1 = identity<string>('myString')
  let output2 = identity<number>(100)
  interface GenericIdentityFn<T> {
    (arg: T): T
  }
  function identity<T>(arg: T): T {
    return arg
  }
  let myIdentity: GenericIdentityFn<number> = identity
  class GenericNumber<T> {
    zeroValue: T
    add: (x: T, y: T) => T
  }
  let myGenericNumber = new GenericNumber<number>()
  myGenericNumber.zeroValue = 0
  myGenericNumber.add=function(x,y){return x+y;};
  console.info(myGenericNumber.add(2,5));

  let stringNumberic=new GenericNumber<string>();
  stringNumberic.zeroValue='abc';
  stringNumberic.add=function(x,y){return `${x}--${y}`};
  console.info(stringNumberic.add('张三丰','诸葛亮'));

rachern avatar Mar 09 '22 15:03 rachern

泛型变量

会根据参数或前面的<>推算出泛型的类型 其声明类型不为 "void" 或 "any" 的函数必须返回值。

function foo<T>(a: T): T {
  return a
}
foo<string>(1) // error

泛型类型

类型是 any,string... 这种,泛型类型就是将泛型作为类型,用在赋值的时候

function foo<T>(a: T): T {
  return a
}
let a: <T>(a: T) => T = foo
a = 1 // error
a = foo // ok

泛型接口

泛型类型还可以用接口去描述

interface bar{
  <T>(a: T): T
}

let a: bar
a = foo // ok
a = 1 // error

上面是将泛型的定义放在了接口里面,还有一种放在接口的写法,这样接口里的其他都可以使用这个泛型。

interface bar<T>{
  (a: T): T
}

interface zoo<T> {
  a: T,
  b: (args: T) => T
}

let c: zoo<string>

c = [1] // error
c = () => 1 // error
c = {
  a: '1',
  b: (x) => '1'
}

泛型约束

通过 extends 决定泛型可用的属性,确保属性存在

function foo<T>(a: T) {
  a.length // error
}

function foo<T extends []>(a: T) {
  a.length // ok, 但同时 a 继承了数组的其他属性方法。 a.reverse // ok
}

interface bar {
  length: number
}
function foo<T extends bar>(a: T) {
  a.length // ok, 但是 a 只有一个 length 属性
}

const obj = { a: 1, b: 2 }
function foo<T, U extends keyof T>(o: T, k: U): T[U] {
  return o[k]
}

foo(obj, 'x') // error

泛型类

泛型类和泛型接口类似,通过外面传入类型可以提供内部使用,同时和泛型约束一样的地方在于可以约束内部属性。

class foo<T>{
  bar: T

  constructor(x: T) {
    this.bar = x
  }
}

new foo<string>('1')
function create<T extends foo<string>>(ins: new (x: string) => T): T {
  return new ins('1')
}

create(foo).bar = '1' // ok
create(foo).bar = 1 // error

zcma11 avatar Mar 09 '22 19:03 zcma11

泛型是指在定义函数,接口,类的时候,不明确指定参数的类型,而是用一个变量接收,而在使用的时候根据传入值的类型明确参数的类型,这样大大增加了灵活性和可复用性。 应用场景是一些无法明确输入参数类型,但是又需要根据输入参数类型做相应约束的场景。

zhenyuWang avatar Mar 10 '22 01:03 zhenyuWang