TypeScript 入门

课程地址

ts 开发环境搭建

npm i -g typescript

查看安装位置:

$ npm root -g
C:\Users\Daniel\AppData\Roaming\npm\node_modules

创建 hello.ts

console.log("hello, ts");

编译 ts 文件,得到 js 文件:

$ tsc foo.ts

类型声明

后置的类型声明

let a: number;a = 10;
a = 33;
// a = "hello";let b: string = "hello";
let c = true;   // Automatic type inferencefunction sum(a: number, b: number): number {return a + b;
}console.log(sum(1, 2));

类型

在这里插入图片描述

// 字面量类型
let a: 10;  // const a = 10;// 联合类型
let b: "male" | "female";
let c: boolean | string;
c = true;
c = "hello"// any 与 unknown
let d: any;
d = "hello";let e: unknown;
e = "hello";let s: string = d;
// s = e;   Type 'unknown' is not assignable to type 'string'
s = e as string;
s = <string>e;function f(): void {return;
}function f2(): never {  // 永远不会返回结果,终止进程throw new Error("error");
}

unknown 本质上是一个类型安全的 any

// 对象类型
let b: {name: string,age?: number,   // ? -> optional
};b = {name: "sunwukong"
};let c: {name: string,[propName: string]: any,
};// 函数类型
let d: (a: number, b: number) => number;d = function(a, b) {return a + b;
}// 数组类型
let e: string[];
e = ["a", "b", "c"];let g: Array<number>;
g = [1, 2, 3];// 元组
let h: [string, string];// enum
enum Gender {Male = 0,Female = 1,
}let p: {name: string, gender: Gender}p = {name: "sunwukong",gender: Gender.Male,
}// & 类型
let j: {name: string} & {age: number};// 类型别名
type t1 = 1 | 2 | 3 | 4 | 5;
let m: t1;

tsc 编译选项

自动编译文件

tsc foo.ts -w	# 文件改变时自动编译
tsc		# 根据 tsconfig.json 编译

tsconfig.json

{/*** 表示任意目录* 表示任意文件*/"include": ["./*"],"exclude": ["foo.ts"],// "files": ["./app.ts", "./index.ts"],"compilerOptions": {"target": "ES6",     // 指定 es 版本// "module": "ES6",// "lib": ["DOM"]"outDir": "./dist",// "outFile": "./dist/app.js",  // 将编译结果合并到 app.js"allowJs": false,"checkJs": false,   // 对 js 也做类型检查"removeComments": false,"noEmit": true,     // 不生成编译后的文件,只检查"noEmitOnError": true,   // 当有错误时不生成编译后的文件"strict": true,     // 打开下面的所有严格检查/*"alwaysStrict": true,   // -> use strict"noImplicitAny": true,"noImplicitThis": true,"strictNullChecks": true,*/},
}

使用 webpack 打包 ts 代码

npm init -y		# 初始化项目
npm i -D webpack webpack-cli typescript ts-loader

配置 webpack.config.js

const path = require("path");module.exports = {entry: "./src/index.ts",output: {path: path.resolve(__dirname + "/dist"),filename: "bundle.js",},module: {rules: [{test: /\.ts$/,use: "ts-loader",exclude: /node_modules/}]},mode: 'development',
}

配置 tsconfig.json

{"compilerOptions": {"module": "es6","target": "es6","strict": true,}
}

package.json 中增加 script 配置

  "scripts": {"test": "echo \"Error: no test specified\" && exit 1","build": "webpack"},

最后 npm run build 即可

安装 3 个插件:

npm i -D html-webpack-plugin	# 生成 html 测试文件
npm i -D webpack-dev-server		# 编辑后自动重启服务
npm i -D clean-webpack-plugin	# 清除 dist 目录再构建
npm i -D @babel/core @babel/preset-env babel-loader core-js

package.json 中编写 webpack-server 的启动脚本:

  "scripts": {"start": "webpack serve --open"},

webpack.config.ts 中引入插件(使用 template.html 作为生成模板):

const path = require("path");
const HTMLWebpackPlugin = require("html-webpack-plugin");
const {CleanWebpackPlugin} = require("clean-webpack-plugin");module.exports = {entry: "./src/index.ts",output: {path: path.resolve(__dirname + "/dist"),filename: "bundle.js",},module: {rules: [{test: /\.ts$/,use: [{loader: "babel-loader",options: {presets: [["@babel/preset-env",{targets: {"chrome": "88"},"corejs": "3","useBuiltIns": "usage"  // 按需加载}]]}},"ts-loader"],exclude: /node_modules/}]},mode: 'development',plugins: [new HTMLWebpackPlugin({// title: "mytitle"template: "./src/template.html"}),new CleanWebpackPlugin(),],resolve: {  // 设置引用模块extensions: [".ts", ".js"]}
}

OOP

class

class Person {name: string = "sunwukong";static age: number = 18;readonly gender: string = "M";sayHello() {console.log("hello");}
}let p = new Person();console.log(p);
console.log(Person.age);
p.sayHello();

构造函数和 this

class Dog {name: string;age: number;constructor(name: string, age: number) {this.name = name;this.age = age;}bark() {console.log(`${this.name}: wangwang`);}
}let d = new Dog("wangcai", 4);console.log(d);
d.bark();

继承

class Animal {name: string;age: number;constructor(name: string, age: number) {this.name = name;this.age = age;}sayHello() {console.log("sayHello()");}
}class Dog extends Animal{run(){console.log(`${this.name} is running`);}sayHello(): void {  // 子类重写父类方法console.log("wangwangwang");}
}class Cat extends Animal{sayHello(): void {  // 子类重写父类方法console.log("miaomiaomiao");}
}const d1 = new Dog("wangcai", 5);
console.log(d1);
d1.sayHello();const c1 = new Cat("mimi", 3);
c1.sayHello();

super

super 表示父类

class Animal {name: string;constructor(name: string) {this.name = name;}sayHello() {console.log("sayHello()");}
}class Dog extends Animal {age: number;constructor(name: string, age: number) {super(name);this.age = age;}sayHello(): void {console.log("wangwangwang");}
}const d1 = new Dog("wangcai", 3);
console.log(d1);    // Dog { name: 'wangcai', age: 3 }
d1.sayHello();      // wangwangwang

抽象类

使用 abstract 修饰的类,不能用于实例化对象,只能被继承

抽象类中可以添加抽象方法,抽象方法必须被子类重写

abstract class Animal {name: string;constructor(name: string) {this.name = name;}abstract sayHello(): void;  // 必须被子类重写
}class Dog extends Animal {sayHello(): void {console.log("wangwangwang");}
}const d1 = new Dog("wangcai");
console.log(d1);    // Dog { name: 'wangcai', age: 3 }
d1.sayHello();      // wangwangwang

接口

用来定义一个类的结构(一个类应该包含哪些属性和方法,做类型限制)

接口中的所有属性都不能带有实际的值,接口只定义对象的结构(全是抽象方法),而不考虑实际值

interface Person{name: string;age: number;
}// 接口可以分离定义
interface Person {gender: string;sayHello(): void;
}class Male implements Person {name: string;age: number;gender: string;constructor(name: string, age: number, gender: string) {this.name = name;this.age = age;this.gender = gender;}sayHello(): void {console.log("hello");}
}

属性访问控制

class Person {private _name: string;private _age: number;constructor(name: string, age: number) {this._name = name;this._age = age;}get name() {        // per.namereturn this._name;}set name(name: string) {this._name = name;}get age() {return this._age;}set age(age: number) {if (age >= 0) {this._age = age;}}
}const p1 = new Person("sunwukong", 18);
console.log(p1);p1.name = "zhubajie";
console.log(p1);
console.log(p1.age);class C {// 直接将属性和访问控制定义在构造函数中constructor(public name: string, public age: number) {}
}

泛型

function fn<T> (a: T): T {return a;
}fn(10);
fn<string>("hello");function bar<T, K>(a: T, b: K): T {console.log(b);return a;
}bar<number, string>(10, "hello");interface Inter {length: number;
}
// 使用接口约束泛型的类型参数
function foo<T extends Inter>(a: T): number {return a.length;
}foo("123");     // string 有 length
foo({length: 10});// 类的泛型
class C<T> {name: T;constructor(name: T) {this.name = name;}
}const c = new C<string>("sunwukong");

贪吃蛇练习

// package.json
{"name": "snake","version": "1.0.0","description": "","main": "index.js","scripts": {"test": "echo \"Error: no test specified\" && exit 1","build": "webpack","start": "webpack serve --open"},"keywords": [],"author": "","license": "ISC","devDependencies": {"@babel/core": "^7.23.9","@babel/preset-env": "^7.23.9","babel-loader": "^9.1.3","clean-webpack-plugin": "^4.0.0","core-js": "^3.35.1","css-loader": "^6.10.0","html-webpack-plugin": "^5.6.0","less": "^4.2.0","less-loader": "^12.2.0","style-loader": "^3.3.4","ts-loader": "^9.5.1","typescript": "^5.3.3","webpack": "^5.89.0","webpack-cli": "^5.1.4","webpack-dev-server": "^4.15.1"}
}
// tsconfig.json
{"compilerOptions": {"module": "es6","target": "es6","strict": true,"noEmitOnError": true}
}
// webpack.config.ts
const path = require("path");
const HTMLWebpackPlugin = require("html-webpack-plugin");
const {CleanWebpackPlugin} = require("clean-webpack-plugin");module.exports = {entry: "./src/index.ts",output: {path: path.resolve(__dirname + "/dist"),filename: "bundle.js",},module: {rules: [{test: /\.ts$/,use: [{loader: "babel-loader",options: {presets: [["@babel/preset-env",{targets: {"chrome": "88"},"corejs": "3","useBuiltIns": "usage"  // 按需加载}]]}},"ts-loader"],exclude: /node_modules/},{test: /\.less$/,use: ["style-loader","css-loader","less-loader"]}]},mode: 'development',plugins: [new HTMLWebpackPlugin({// title: "mytitle"template: "./src/template.html"}),new CleanWebpackPlugin(),],resolve: {  // 设置引用模块extensions: [".ts", ".js"]}
}
// index.ts
import "./style/index.less"
import Food from "./modules/food"
import ScorePanel from "./modules/score_panel"
import GameControl from "./modules/game_control";const f = new Food();
f.change();const gc = new GameControl();
// snake.ts
class Snake {head: HTMLElement;bodies: HTMLCollection;element: HTMLElement;constructor() {this.head = document.querySelector("#snake > div")!;this.bodies = document.getElementById("snake")!.getElementsByTagName("div");this.element = document.getElementById("snake")!;}get X() {return this.head.offsetLeft;}get Y() {return this.head.offsetTop;}set X(x: number) {if (this.X === x) return;if (x < 0 || x > 290) {throw new Error("snake_dead");}if (this.bodies[1] && (this.bodies[1] as HTMLElement).offsetLeft === x) {if (x > this.X) {x = this.X - 10;} else {x = this.X + 10;}}this.moveBody();this.head.style.left = x + "px";this.checkHeadBody();}set Y(y: number) {if (this.Y === y) return;if (y < 0 || y > 290) {throw new Error("snake_dead");}if (this.bodies[1] && (this.bodies[1] as HTMLElement).offsetTop === y) {if (y > this.Y) {y = this.Y - 10;} else {y = this.Y + 10;}}this.moveBody();this.head.style.top = y + "px";this.checkHeadBody();}addBody() {this.element.insertAdjacentHTML("beforeend", "<div></div>");}moveBody() {for (let i = this.bodies.length - 1; i > 0; i--) {let X = (this.bodies[i - 1] as HTMLElement).offsetLeft;let Y = (this.bodies[i - 1] as HTMLElement).offsetTop;(this.bodies[i] as HTMLElement).style.left = X + "px";(this.bodies[i] as HTMLElement).style.top = Y + "px";}}checkHeadBody() {for (let i = 1; i < this.bodies.length; i++) {let bd = this.bodies[i] as HTMLElement;if (this.X === bd.offsetLeft && this.Y === bd.offsetTop) {throw new Error("snake_dead");}}}
}
export default Snake;
// score_panel.ts
class ScorePanel {score = 0;level = 1;scoreEle: HTMLElement;levelEle: HTMLElement;maxLevel: number;upScore: number;constructor(maxLevel: number = 10, upScore: number = 10) {this.scoreEle = document.getElementById("score")!;this.levelEle = document.getElementById("level")!;this.maxLevel = maxLevel;this.upScore = upScore;}addScore() {this.scoreEle.innerHTML = ++this.score + "";if (this.score % this.upScore === 0) {this.levelUp();}}levelUp() {if (this.level < this.maxLevel) {this.levelEle.innerHTML = ++this.level + "";}}
}
export default ScorePanel;
// game_control.ts
import Snake from "./snake";
import Food from "./food";
import ScorePanel from "./score_panel";class GameControl {snake: Snake;food: Food;scorePanel: ScorePanel;direction: string = "";isLive = true;constructor() {this.snake = new Snake();this.food = new Food();this.scorePanel = new ScorePanel();this.init();}keydownHandler = (event: KeyboardEvent) => {this.direction = event.key;}init() {document.addEventListener("keydown", this.keydownHandler);this.run();}run() {let X = this.snake.X;let Y = this.snake.Y;switch(this.direction) {case "ArrowUp":Y -= 10;break;case "ArrowDown":Y += 10;break;case "ArrowLeft":X -= 10;break;case "ArrowRight":X += 10;break;}this.checkEat(X, Y);try {this.snake.X = X;this.snake.Y = Y;} catch (e) {alert((e as Error).message);this.isLive = false;}this.isLive && setTimeout(this.run.bind(this), 300 - (this.scorePanel.level - 1) * 30);}checkEat(x: number, y: number) {if (x === this.food.X && y === this.food.Y) {console.log("ate food");this.food.change();this.scorePanel.addScore();this.snake.addBody();}}}export default GameControl;
// food.ts
class Food {element: HTMLElement;constructor() {// `!` 表示判定该语句的结果不可能为空this.element = document.getElementById("food")!;}get X() {return this.element.offsetLeft;}get Y() {return this.element.offsetTop;}change() {let left = Math.round(Math.random() * 29)* 10;let top = Math.round(Math.random() * 29)* 10;this.element.style.left = top + "px";this.element.style.top = left + "px";}
}
export default Food;
// index.less
* {margin: 0;padding: 0;box-sizing: border-box;
}body {font: bold 20px Courier;
}#main {width: 360px;height: 420px;background-color: #b7d4a8;margin: 100px auto;border: 10px solid black;border-radius: 10px;display: flex;flex-flow: column;align-items: center;justify-content: space-around;#stage {width: 304px;height: 304px;border: 2px solid black;position: relative;#snake {&>div {width: 10px;height: 10px;background-color: black;border: 1px solid #b7d4a8;position: absolute;}}#food {width: 10px;height: 10px;position: absolute;left: 40px;top: 100px;display: flex;flex-flow: row wrap;justify-content: space-between;align-content: space-between;&>div {width: 4px;height: 4px;background-color: black;}}}#score-panel {width: 300px;display: flex;justify-content: space-between;}}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/467605.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

《金融人工智能:用python实现ai量化交易》

融合了数学、python、深度学习以及金融知识&#xff0c;是本推荐的好书。请收藏本文&#xff0c;读后再给大学总结。

Toolify.ai 帮助你发现最好的 AI 网站和 AI 工具

&#x1f349; CSDN 叶庭云&#xff1a;https://yetingyun.blog.csdn.net/ 人工智能作为一门前沿科技领域&#xff0c;吸引着越来越多的人关注和投入。首先&#xff0c;让我们探讨一下为什么对人工智能感兴趣是值得的&#xff1a; 科技进步与应用&#xff1a;近年来&#xff0c…

红队笔记Day3-->隧道上线不出网机器

昨天讲了通过代理的形式&#xff08;端口转发&#xff09;实现了上线不出网的机器&#xff0c;那么今天就来讲一下如何通过隧道上线不出网机器 目录 1.网络拓扑 2.开始做隧道&#xff1f;No&#xff01;&#xff01;&#xff01; 3.icmp隧道 4.HTTP隧道 5.SSH隧道 1.什么…

2024.2.6 模拟实现 RabbitMQ —— 数据库操作

目录 引言 选择数据库 环境配置 设计数据库表 实现流程 封装数据库操作 针对 DataBaseManager 单元测试 引言 硬盘保存分为两个部分 数据库&#xff1a;交换机&#xff08;Exchange&#xff09;、队列&#xff08;Queue&#xff09;、绑定&#xff08;Binding&#xff0…

OWASP TOP10

OWASP TOP10 OWASP网址&#xff1a;http://ww.owasp.org.cn A01&#xff1a;失效的访问控制 例如&#xff1a;越权漏洞 案例1&#xff1a; 正常&#xff1a;每个人登录教务系统&#xff0c;只能查询自己的成绩信息 漏洞&#xff1a;张三登录后可以查看自己的成绩 例如&…

springboot176基于Spring Boot的装饰工程管理系统

简介 【毕设源码推荐 javaweb 项目】基于springbootvue 的 适用于计算机类毕业设计&#xff0c;课程设计参考与学习用途。仅供学习参考&#xff0c; 不得用于商业或者非法用途&#xff0c;否则&#xff0c;一切后果请用户自负。 看运行截图看 第五章 第四章 获取资料方式 **项…

【51单片机】LCD1602(江科大)

1.LCD1602介绍 LCD1602(Liquid Crystal Display)液晶显示屏是一种字符型液晶显示模块,可以显示ASCII码的标准字符和其它的一些内置特殊字符,还可以有8个自定义字符 显示容量:162个字符,每个字符为5*7点阵 2.引脚及应用电路 3.内部结构框图 屏幕: 字模库:类似于数码管的数…

探索Gorm - Golang流行的数据库ORM框架

&#x1f3f7;️个人主页&#xff1a;鼠鼠我捏&#xff0c;要死了捏的主页 &#x1f3f7;️系列专栏&#xff1a;Golang全栈-专栏 &#x1f3f7;️个人学习笔记&#xff0c;若有缺误&#xff0c;欢迎评论区指正 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&…

react【四】css

文章目录 1、css1.1 react和vue css的对比1.2 内联样式1.3 普通的css1.4 css modules1.5 在react中使用less1.6 CSS in JS1.6.1 模板字符串的基本使用1.6.2 styled-components的基本使用1.6.3 接受传参1.6.4 使用变量1.6.5 继承样式 避免代码冗余1.6.6 设置主题色 1.7 React中添…

波奇学Linux:文件缓冲区

问题导入 文件流输出直接向显示器和重定向文件有不一样的表现 分别向显示器文件输出四个语句&#xff0c;最后fork创建子进程。 当程序运行时和程序重定向到文件中&#xff0c;输出的内容不一样。 重定向时c库函数&#xff08;printf,fprintf,fwrite&#xff09;调用了两次&…

Codeforces Round 303 (Div. 2)C. Kefa and Park(DFS、实现)

文章目录 题面链接题意题解代码总结 题面 链接 C. Kefa and Park 题意 求叶节点数量&#xff0c;叶节点满足&#xff0c;从根节点到叶节点的路径上最长连续1的长度小于m 题解 这道题目主要是实现&#xff0c;当不满足条件时直接返回。 到达叶节点后统计答案&#xff0c;用…

片上网络NoC(3)——拓扑指标

目录 一、概述 二、指标 2.1 与网络流量无关的指标 2.1.1 度&#xff08;degree&#xff09; 2.1.2 对分带宽&#xff08;bisection bandwidth&#xff09; 2.1.3 网络直径&#xff08;diameter&#xff09; 2.2 与网络流量相关的指标 2.2.1 跳数&#xff08;hop coun…