TypeScript
写在前面
本章内容比较多,分成多个模块标题学习本章之前,建议先看前面两章
vue指令复习: https://blog.csdn.net/qq_44501608/article/details/136557622
vue3.0入门结构语法关键字生命周期:https://blog.csdn.net/qq_44501608/article/details/136559287
TypeScript(ts)
中文文档:https://ts.nodejs.cn/
手册:https://ts.nodejs.cn/docs/handbook/typescript-from-scratch.html
安装:https://ts.nodejs.cn/download 或者手动创建vue3.0的时候勾选ts
最核心的区别,JavaScript弱类型语言,编译期间可能不太清楚静态类型的错误
TypeScript提供了这个检测,编辑器期间尽快查明错误
TypeScript支持JavaScript的语法:
静态类型检测
同java
JavaScript在编写小程序时,这种怪癖(可以访问不存在的属性,“”==0)很烦人但可以管理;在编写包含数百或数千行代码的应用时,这些不断出现的意外是一个严重的问题
例子一:
const obj = { width: 10, height: 15 };
const area = obj.width * obj.heigth;
TypeScript报错信息: Property ‘heigth’ does not exist on type ‘{ width: number; height: number; }’. Did you mean ‘height’?Property ‘heigth’ does not exist on type ‘{ width: number; height: number; }’. Did you mean ‘height’?
实际浏览器console不会报错:
输出以后是非数,但这样的结果应该在编译期间就报错了。
而上述TypeScript报错信息,说的是该类型不匹配,并且提示,你是否说的是height
所以: 前面关于 obj.heigth
的错误不是语法错误:它是以不正确的方式使用某种值(类型)的错误,因为对于js来讲,那个计算是合理的,因为他可以访问空元素
例子二:
小节:
- 运行时擦除,TS好像java的泛型,他旨在编译期间提示错误,运行期间按javaScript的语法要求来,相当于JavaScript安装了一个强语言类型的检测
- typeScript 不提供任何额外的运行时库,使用js的即可
- 编写期间创建变量分配了特定值以后,TypeScript将使用该值的类型,推断类型
定义类型
定义全局类型:
// 声明全局变量
declare var appName: string;
// 声明全局函数
declare function getVersion(): string;
// 声明模块
declare module 'ChartLib' {
export function createChart(elementId: string, config: any): void;
}
// 声明类
declare class Logger {
static log(message: string): void;
static error(message: string): void;
}
使用:
// 使用全局变量
console.log(`Application Name: ${appName}`);
// 使用全局函数
console.log(`Version: ${AppUtils.getVersion()}`);
// 使用外部模块
import * as ChartLib from 'ChartLib';
ChartLib.createChart('myChart', { type: 'line', data: [1, 2, 3] });
// 使用全局类
Logger.log('This is a log message');
Logger.error('This is an error message');
TypeScript 支持 JavaScript 语言的扩展,它为你提供了告诉 TypeScript 类型应该是什么的地方
js可以这样写:
const user={name:"Hayes",id:0}
对于TypeScript语法(下文都简称ts),他也是支持的,并且会推断name,id的类型
interface User{name:string,id:number}
// 没有赋值自己定义类型,:TypeName 如下方式使用
const user: User = {name: "Hayes",id:0,}
同时,他也是支持javaScript支持的面向对象的声明的:
interface User {
name: string;
id: number;
}
class UserAccount {
name: string;
id: number;
constructor(name: string, id: number) {
this.name = name;
this.id = id;
}
}
const user: User = new UserAccount("Murphy", 1);
你也可以定义方法时:
// 定义该方法需要满足User接口的参数
function deleteUser(user: User) {
// ...
}
// 定义该方法需要返回满足User接口的参数
function getAdminUser(): User {
//...
}
特殊类型/基础类型
JavaScript 中已经有一小部分基础类型可用:boolean
、bigint
、null
、number
、string
、symbol
、undefined
,可在接口中使用。TypeScript 用更多的东西扩展了这个列表,比如 any
(允许任何东西)、unknown
(确保使用这个类型的人声明了这个类型是什么)、never
(这个类型不可能发生)和 void
(一个函数返回 undefined
或没有返回值)
对于any,unknown,never,void的案例和示例:
any:
any
类型允许将变量设置为任意类型。这在您不希望对变量进行具体类型限制时非常有用,但它同时也意味着放弃了类型检查带来的好处。
let notSure: any = 4;
notSure = "也许是一个字符串";
notSure = false; // 没问题,这确实是一个布尔值
unknown
类型
unknown
类型表示变量可以接受任何类型的值,类似于 any
,但使用时更加安全,因为对 unknown
类型的变量进行操作之前,必须先进行类型判断。
let uncertain: unknown = 4;
uncertain = "可以是任何东西";
uncertain = false;
if (typeof uncertain === "string") {
// 在这里,uncertain 的类型被缩减为 string
console.log(uncertain.toUpperCase()); // 没有类型错误
}
never
类型
never
类型表示那些永远不存在的值的类型。例如,never
类型用于那些总是会抛出异常或根本不会有返回值的函数。
// 抛出异常或者死循环
function error(message: string): never {
throw new Error(message);
}
function infiniteLoop(): never {
while (true) {}
}
void类型
void
类型表示没有任何类型,通常用于没有返回值的函数的返回类型。
// 表示该方法没有返回值
function warnUser(): void {
console.log("这是我的警告信息");
}
组合类型
type类型 type定义, 使用只能使用指定的类型
<script lang="ts" setup>
import {ref} from 'vue';
type MyBool = true | false;
type WindowStates = "open" | "closed" | "minimized";
type LockStates = "locked" | "unlocked";
const bool = ref<MyBool>(true);
const windowState = ref<WindowStates>("open1");
const lockState = ref<LockStates>("locked");
console.log(bool.value);
console.log(windowState.value);
console.log(lockState.value);
// 测试长度
function getLength(obj: string | string[]) {
return obj.length;
}
const str = getLength("123");
console.log(str);
</script>
function wrapInArray(obj: string | string[]) {
if (typeof obj === "string") {
return [obj];
//(parameter) obj: string
}
return obj;
}
ts可以看到编写js的时候报错,但是能够运行出来。
判断类型:
泛型
跟java泛型很类似
<script lang="ts" setup>
import { ref } from 'vue';
interface Backpack<Type> {
add: (obj: Type) => void;
get: () => Type;
}
// 创建一个 Backpack<string> 类型的实例
const backpack: Backpack<string> = {
add: (obj: string) => {
// 实现添加逻辑
console.log(`Adding ${obj}`);
},
get: () => {
// 实现获取逻辑
return 'some string';
},
};
// 正确使用 Backpack 实例
const object = backpack.get(); // 'object' 是一个 string 类型
console.log(object); // 输出: some string
backpack.add('hello'); // 正确的调用,因为我们传入的是一个 string 类型的参数
</script>
TypeScript的OOP-反思类型
结构类型系统
如果两个对象具有相同的形状,则认为它们属于同一类型 ,这个有点扯,
就好像拿着json对象比较
<script lang="ts" setup>
interface Point {
x: number;
y: number;
}
function logPoint(p: Point) {
console.log(`${p.x}, ${p.y}`);
}
// logs "12, 26"
const point = { x: 12, y: 26 };
logPoint(point);
</script>
总结:编译和运行都不报错, 但是并没有使用Point类型传参,只是对象结构一致
TypeScript 中不需要来自 C# 和 Java 的某些构造,例如单例和静态类。
TypeScript 支持许多常见模式,例如实现接口、继承和静态方法
java或者C# 在代码中编写的类型在运行时存在,类型通过它们的声明而不是它们的结构相关。
TypeScript 的类型系统是结构化的,而不是名义上的
小节:反思类型, 结构相同就是同一类型,跟命名无关,可以直接用 案例如下:
<script lang="ts" setup>
interface Pointlike {
x: number;
y: number;
}
interface Named {
name: string;
}
function logPoint(point: Pointlike) {
console.log("x = " + point.x + ", y = " + point.y);
}
function logName(x: Named) {
console.log("Hello, " + x.name);
}
const obj = {
x: 0,
y: 0,
name: "Origin",
};
logPoint(obj);
logName(obj);
</script>
空类型
<script lang="ts" setup>
class Empty {}
function fn(arg: Empty) {
// do something?
}
// No error, but this isn't an 'Empty' ?
fn({ k: 10 });
</script>
这样是可以通过编译 的,因为父类没有属性,我调用的是子类具有Empty所有的结构,因为Empty没有属性,他就跟任意结构保持一致。
相同类型
class Car {
drive() {
// hit the gas
}
}
class Golfer {
drive() {
// hit the ball far
}
}
// No error?
let w: Car = new Golfer();
同上,结构结构