1.TS基本类型

一、TS类型声明

1.在.ts文件中定义变量a,提示无法重新声明块范围变量“a”。

原因分析:TS误以为这些文件将在未来的某个时间合并,所以抛出了变量“重复”的错误。
解决方法:在文件末尾加上export {}即可。(项目中已经有了exports模块化工具后才能使用)

let a: number = 12;
export {}
2.如果变量的声明和赋值是同时进行的,TS可以对变量进行 \color{red}{自动类型检测。}
let b = 13; // 声明变量b 并赋值为13
b = true; // 报错,因为b的类型是number,不能赋值为boolean
3.如果只声明变量不赋值,且没有指定变量的类型,TS会自动判断该变量的类型为 \color{red}{any,(隐式的any)}
// 变量只声明不赋值,且没有指定变量的类型时,TS自动推断变量的类型为any
let c;
c = 1;
c = "hello";
c = true;
4.给函数的 \color{red}{参数}\color{red}{返回值} 声明类型
function sum(a: number, b: number):number {
  return a + b;
}

二、TS基本类型

类型 例子 描述
number 1,2,3 任意数字
string 'hello' 任意字符串
boolean true,false 布尔值true或false
字面量 其本身 限制变量的值就是该字面量的值
any * 任意类型
unknown * 类型安全的any
void 空值(undefined) 没有值(或undefined)
never 没有值 不能是任何值
object {name:'孙悟空'} 任意的JS对象
array [1,2,3] 任意JS数组
tuple [4,5] 元组,TS新增类型,固定长度的数组
enum enum{A,B} 枚举,TS新增类型
1.字面量类型

字面量类型的变量,只能被赋值为指定的值。

// 字面量类型的变量,只能被赋值为指定的值
let d: "male" | "female";
d = "male";
d = "female";
TS类型声明时, \color{red}{|} 代表 \color{red}{或}
// 声明变量类型时,可以用 | 连接多个类型,表示该变量可以是多个类型中的一个
let e: string | number;
e = "hello";
e = 123;
2.any和unknown的区别。

(1)可以把任意类型的值赋值给any或unknown类型的变量。

// any表示任意类型
let c: any;
c = 1;
c = "hello";
c = true;
// unknown 表示未知类型的值
let f: unknown;
f = 10;
f = "hello";
f = true;

(2)any类型的变量可以直接赋值给其他任意类型的变量;unknown类型的变量则不能直接赋值给其他类型的变量,除非对unknown类型的变量做 \color{red}{类型判断}\color{red}{类型断言}

类型断言语法格式:\color{red}{变量 as 类型} 或者 \color{red}{<类型>变量}

let g: string;
g = c; // 不报错,因为c的类型是any
g = f; // 报错,不能将类型“unknown”分配给类型“string”

g = f as string; // 类型断言,告诉编译器f是string类型
g = <string>f; // 类型断言,告诉编译器f是string类型
// 类型判断
if (typeof f === "string") {
  g = f;
}
3.void类型

void表示没有任何类型,一般用于 函数没有返回值 或者 返回undefined。

// void 表示没有任何类型,一般用于函数没有返回值或者返回undefined
function sum(x: number, y: number): void {
  // return undefined;
 }

没有声明函数返回值的类型且函数没有返回值时,函数返回值的类型默认为隐式的void。

4.never类型

never表示不能是任何值,永远不会有返回结果。例如函数内抛出错误。

function sum2(): never { 
  throw new Error("报错了!")
}
5.object类型

{属性名:类型,属性名?:类型,[任意名称:类型]:类型}

  • 不加 \color{red}{?} 表示属性是必须的
  • \color{red}{?} 表示属性是可选的
  • [propName: string]:any 表示该对象中可以添加任意个属性,属性名是string类型,属性值是any类型
// object 表示一个js对象,但这种写法不太常用
let h: object;
h = {};
/*
  常用的写法:{属性名:类型,属性名?:类型,[任意名称:类型]:类型}。
  ? 表示属性是可选的;不加?表示属性是必须的
  [propName: string]:any 表示该对象中可以添加任意个属性,属性名是string类型,属性值是any类型
*/ 
let i: { x: number, y?: string, [propName: string]: any };
i = { x: 1, y: "hello", name: "张三", age: 18 }; // x是必须有的,y可有可无,name和age也是可有可无
// Function 表示一个函数,但这种写法不太常用
let j: Function;
j = function () { };
// 常用的写法:(参数名:类型) => 返回值类型
let k: (a: number, b: string) => number;
k = function (a, b):number { return a + b.length; };
6.array类型

\color{red}{类型[ ]} 或者 \color{red}{Array<类型>}

/*
 * 数组类型的声明:类型[] 或 Array<类型>
*/ 
let l: number[]; // 数组中的元素是number类型
l = [1, 2, 3];

let m: Array<string>; // 数组中的元素是string类型
m = ["a", "b", "c"];
7.tuple类型

元组就是固定长度的数组。

// 元组就是固定长度的数组
let n: [string, number]; // 元组类型,表示一个元组中只能有两个元素,第一个元素是string类型,第二个元素是number类型
n = ["hello", 123];
8.enum类型

\color{red}{enum 自定义枚举名称\{枚举值1,枚举值2\}} 或者 \color{red}{enum 自定义枚举名称\{枚举值1 = 1,枚举值2 = 2\} }

// 枚举类型
enum Gender { Male, Female }; // 定义枚举类型Gender,表示性别,有男和女两种
let o = {name: "张三", gender: Gender.Male}; // 定义对象o,name是字符串,gender是Gender枚举类型
console.log(o.gender === Gender.Male); // true
9.类型的别名

type 类型别名 = 类型

// 类型的别名: type 类型别名 = 类型
type myType = number[]; // myType等价于number类型的数组
let z: myType = [1, 2, 3]; // z的数据类型是myType,一个number类型的数组

三、接口

1.定义类结构

(1)用interface 关键字来定义接口;用 implements 关键字来实现接口。
(2)接口可以用来定义 类的结构,即一个类中应该有哪些属性和方法。
(3)接口中的 属性方法 都是 抽象的(即不能有实际的值),抽象的属性和方法必须被实现(重写)。

// interface关键字来定义接口
interface myInterface {
  name: string;
  sayHello(): void;
}

// implements关键字来实现接口
class MyClass implements myInterface {
  name: string;
  constructor(name: string) {
    this.name = name; // 实现抽象属性
  }
  // 实现抽象方法
  sayHello(): void {
    console.log("你好!");
   }
 }
2.类型声明

(1)接口也可以当做类型声明来使用。
(2)不同的是,接口可以 重复声明,而类型声明不可以。

// A和B是等价的
interface A {
  name: string;
}
interface A {
  age: number;
}
type B = {
  name: string;
  age: number;
}

四、泛型

1. 什么是泛型

(1)在定义 函数接口 时,不预先指定具体的类型,而在 使用时 再指定类型的一种特性。
(2)使用 any 会跳过类型检查,且会丢失参数和返回值之间的类型约束关系。

2. 泛型函数

(1)重点在于用 function 关键字 定义函数 时,怎么使用泛型。
(2)基础用法

// 泛型函数,T和K是类型变量,可以用任意字母表示
function fn<T,K>(a: T, b: K): T {
  console.log(b);
  return a;
}
fn<number,string>(10, "hello"); // 指定T是number类型,K是string类型
fn(10, "hello");                // 不指定类型,TS自动推断T是number类型,K是string类型

(3)实际用法——用function关键字声明函数组件

① 用 function 定义了一个函数组件,用到了泛型T,并用extends关键字对T进行了 泛型约束
② 入参的类型是 泛型接口 类型,名为 TableProps<T>。
③ 返回值是 JSX.Element类型。

import React from 'react';

// 泛型接口定义组件 Props
interface TableProps<T> {
  data: T[];
  columns: Array<{
    key: keyof T;
    title: string;
    render?: (value: T[keyof T], record: T) => React.ReactNode;
  }>;
}

// 泛型函数组件
function GenericTable<T extends { id: string }>({
  data,
  columns
}: TableProps<T>): JSX.Element {
  return <div></div>
}
3. 泛型接口

(1)本质就是 接口,而这个接口中用到了 泛型,目的是指定 变量 的类型。
(2) 基础用法

// 泛型接口
interface ApiResponse<T> {
    code: number;
    message: string;
    data: T;  // data 的类型由使用接口时指定
}
// 用户信息的接口响应数据
let userResponse: ApiResponse<{ name: string; age: number }> = {
    code: 200,
    message: "Success",
    data: { name: "Alice", age: 30 } // data 必须是 { name: string; age: number }
};

(2) 实际用法——用箭头函数声明函数组件

① 这里用 箭头函数 定义了一个 函数组件,并用 变量 进行存接收存储。
React.FC<UserProps>:这是对组件整体的类型注解,而组件存储到了变量中,所以实际修饰的是 \color{red}{变量},变量的类型就是 \color{red}{泛型接口}
React.FC 是 React已经定义好的 内置泛型接口, 表示 变量的类型React 函数组件
<UserProps> 是泛型参数,React.FC这个泛型变量接受到泛型参数后,在内部用它指定了组件的 props 类型

// 1. 定义 Props 接口
interface UserProps {
  name: string;
  age: number;
  isActive?: boolean; // 可选属性
}

// 2. 组件类型注解
const UserCard: React.FC<UserProps> = (props) => {
  // 此时 props 的类型已经被推断为 UserProps
  // 包含 name: string, age: number, isActive?: boolean
  // 以及 React.FC 隐含的 children?: React.ReactNode
}
4. 泛型类
// 泛型类
class B<T> {
  name: T;
  constructor(name: T) {
    this.name = name;
  }
}
let b1 = new B<string>("张三"); // 指定T是string类型
5. 泛型约束

如果不希望泛型可以是任何类型,而是希望它 至少满足某些条件。这时就需要使用 extends 关键字来实现泛型约束。

// 定义一个接口,表示必须有length属性
interface Lengthwise {
  length: number;
}
// 定义一个泛型函数,T必须是Lengthwise类型或其子类型
function fn1<T extends Lengthwise>(a: T): number {
  return a.length; // 现在可以安全地访问length属性
}
6. 泛型默认值

...

五、常用的内置类型工具

1. Omit<T, K> 泛型工具类型

(1)用于从 类型T排除 指定的 属性集合K,生成一个 新的类型

type myNewType = Omit<T, K>

type myNewType= Omit<myOldType,"name" | "age">  // myNewType中包含myOldType中,除了name和age之外的所有类型。
2. Partial<T> 泛型工具类型

(1)Partial 将类型 T 的所有属性都转换为 可选属性(即添加 ? 修饰符)。
(2)Partial 只会影响对象的 直接属性,不会递归地将嵌套对象的属性变为可选。

type myNewType = Partial<T>

/*
*  1.定义一个变量partialUser,变量类型是用 Partial修饰后的 myOldType类型。
*  2.变量 partialUser可以只包含 myOldType 类型的部分属性。
*/ 
let partialUser: Partial<myOldType> = { name: '张三', age: 25 };
3. 常用类型工具

(1)Partial<T>:将类型 T 的所有属性设置为可选的。
(2)Required<T>:将类型 T 的所有属性设置为必需的。
(3)Readonly<T>:将类型 T 的所有属性设置为只读的。
(4)Record<K, T>:构造一个类型,其属性名的类型为 K,属性值的类型为 T。
(5)Pick<T, K>:从类型 T 中选取一组属性 K 来构造类型。
(6)Omit<T, K>:从类型 T 中排除一组属性 K 来构造类型。
(7)Exclude<T, U>:从类型 T 中排除那些可以赋值给 U 的类型。
(8)Extract<T, U>:从类型 T 中提取那些可以赋值给 U 的类型。
(9)NonNullable<T>:从 T 中排除 null 和 undefined。
(10)Parameters<T>:由函数类型 T 的参数类型组成的元组类型。
(11)ReturnType<T>:函数类型 T 的返回值类型。
(12)InstanceType<T>:构造函数类型 T 的实例类型。
(13)ThisParameterType<T>:提取函数类型 T 的 this 参数类型,如果没有则返回 unknown。
(14)OmitThisParameter<T>:从函数类型 T 中移除 this 参数。
(15)ThisType<T>:用于标记上下文 this 类型的工具类型。

interface User {
  name: string;
  age: number;
  email?: string;
}

// (1)Partial: 所有属性变为可选
type PartialUser = Partial<User>;
// 等价于 { name?: string; age?: number; email?: string; }

// (2)Required: 所有属性变为必选
type RequiredUser = Required<User>;
// 等价于 { name: string; age: number; email: string; }

// (3)Readonly: 所有属性变为只读
type ReadonlyUser = Readonly<User>;
// 等价于 { readonly name: string; readonly age: number; readonly email?: string; }

// (4)Record: 构建一个类型,其键为字符串,值为User
type UserRecord = Record<string, User>;

// (5)Pick: 选取User中的'name'和'age'
type UserNameAge = Pick<User, 'name' | 'age'>;
// 等价于 { name: string; age: number; }

// (6)Omit: 排除User中的'age'
type UserWithoutAge = Omit<User, 'age'>;
// 等价于 { name: string; email?: string; }

// (7)Exclude: 从联合类型中排除某些类型
type T0 = Exclude<"a" | "b" | "c", "a">; // "b" | "c"

// (8)Extract: 从联合类型中提取某些类型
type T1 = Extract<"a" | "b" | "c", "a" | "f">; // "a"

// (9)NonNullable: 排除null和undefined
type T2 = NonNullable<string | number | null | undefined>; // string | number

// (10)Parameters: 获取函数的参数类型
declare function f1(arg: { a: number; b: string }): void;
type T3 = Parameters<typeof f1>; // [{ a: number; b: string }]

// (11)ReturnType: 获取函数的返回类型
type T4 = ReturnType<() => string>; // string

// (12)InstanceType: 获取构造函数的实例类型
class C {
  x = 0;
  y = 0;
}
type T5 = InstanceType<typeof C>; // C

// (13)ThisParameterType: 获取函数的this参数类型
function toHex(this: number) {
  return this.toString(16);
}
type T6 = ThisParameterType<typeof toHex>; // number

// (14)OmitThisParameter: 移除this参数
type T7 = OmitThisParameter<typeof toHex>; // () => string

// (15)ThisType: 用于标记对象中方法的this类型
interface MyObject {
  text: string;
  highlight: () => void;
}
type MyObjectThis = ThisType<{ enable: () => void }>;
// 通常与具体对象定义一起使用,例如在选项对象中指定this类型

六、Typescript基本使用

(1)安装,npm install -g typescript。
(2)配置typescript.config.ts文件。(不配置也可以直接进行第三步)
(3)命令行里输入 tsc 文件名.ts进行编译;或者命令行输入tsc -w,当前ts文件变更时会自动编译到js文件。
(4)在项目里使用时,可以结合webpack或者vite等打包工具,进一步配置webpack或者vite。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容