TypeScript on the way:学习TypeScript

news2024/11/23 21:06:32

个人博客:Sekyoro的博客小屋
个人网站:Proanimer的个人网站

早该学学了.

之前写过Python的类型系统,如果对于写C++,Java,C#等这类语言来说,typing根本不成问题,所以理解TypeScript也不是问题.

特殊的类型

any,unknown与never

any,unknown是"顶层类型",never是"底层类型".never类型是所有类型共有的,any类型基本没有限制,unknown类型不能直接调用并且运算是有限的,只能进行比较运算.推荐使用unknown代替any然后使用as转换类型.

类型系统

String与string,Number与number

String与string是不同的,前者是可以包含后者的.但是在ts中,很多方法只能使用后者.

所以推荐只使用后者.

image-20240211171858237

let obj: Object;
let obj2:{};
obj = { name: "John" };
obj = true;

此外Object类型包括除了undefined和null的基本类型.所以这并不符合直觉,推荐使用object

let obj3:object;
obj3 = {name:"John"};
obj3 = 13; //报错 不能将number分配给类型object

object类型包含对象,数组,函数.

const ccx = { foo: 1 };
ccx.foo = 2;
let t = { foo: 1 };
t.foo = 3;
let hh:object = {foo:1}
// hh.foo 报错 类型不对

此外undefined和null也可以赋值为number,object等等.

TypeScript中单个值也是类型成为值类型

let t: "dfasdf";
const xy = "https";
console.log(xy);

将多个类型组合起来就是联合类型,如果严格检查也就是设置strictNullChecks,使得其他类型变量不能被赋值为undefined或null.这个时候就可以用联合类型

let setting: true | false;

let gender: "male" | "female";

let rainbowColor: "赤" | "橙" | "黄" | "绿" | "青" | "蓝" | "紫";
let name: string | null;

name = "John";
name = null;

对象的合成可以给对象添加新的属性,属于交叉类型.

let obj5: { foo: string } & { bar: number };

类型别名

type Age = number;
let age:Age =  55;

跟Python的typing和Go语言类似.

数组 元组

let arr: number[] = [];
let arr2: (number|string)[] = [];
let arr3: Array<number> = [];

const数组中的元素是可以改变的,所以在ts中增加了readonly,readonly数组是原本数组的子类型.

const arr5: number[] = [0, 1];
arr5[0] = 3;
let arr6: readonly number[] = arr5;

声明readonly数组

let aa: readonly number[] = [1, 2, 3];
let a1: ReadonlyArray<number> = [1, 2, 3];
let a2: Readonly<number[]> = [];
let a3 = [] as const;

TypeScript 推断类型时,遇到const命令声明的变量,如果代码里面没有注明类型,就会推断该变量是值类型。

const命令声明的变量,如果赋值为对象,并不会推断为值类型,这是因为 JavaScript 里面,const变量赋值为对象时,属性值是可以改变的(数组等同理)

元组tuple

const s: [string, string, boolean] = ["a", "b", true];

使用元组时必须声明类型不然会默认数组.

let ot: [number, string?] | undefined = [1];

使用扩展运算符可以不下成员数量的元组.

元组也有只读元组

let readonlyTuple: readonly [number] = [1];
let point = [3, 4] as const;

symbol类型

symbol主要用于类的属性.

ts增加了unique symbol作为symbol的子类型.

// 正确
const x: unique symbol = Symbol();

// 报错
let y: unique symbol = Symbol();
const x: unique symbol = Symbol();
// 等同于
const x = Symbol();

const a: unique symbol = Symbol();
const b: typeof a = a; // 正确

感觉平常可能用不上…

函数 对象 interface

function hello(txt: string): void {
  console.log("hello " + txt);
}

// 写法一
const hello = function (txt: string) {
  console.log("hello " + txt);
};

// 写法二
const hello: (txt: string) => void = function (txt) {
  console.log("hello " + txt);
};

函数声明与函数变量声明.前者需要声明参数类型,否则默认为any.后者可以在选择在赋值时写出类型或者在声明变量时添加类型.此外还有这种写法

let add: {
  (x: number, y: number): number;
};

add = function (x, y) {
  return x + y;
};
箭头函数
const repeat = (str: string, times: number): string => str.repeat(times);

另外使用?表示可选参数

function f(x?: number) {
  // ...
}

f(); // OK
f(10); // OK

默认值也类似.

function createPoint(x: number = 0, y: number = 0): [number, number] {
  return [x, y];
}

createPoint(); // [0, 0]

rest参数也可以用于将多个值包裹为数组或元组

function joinNum(...nums: [...number[]]): string {
  console.log(nums);
  return nums.join(" ");
}
joinNum(1, 2, 3, 4, 5);


function joinNumAndString(...args: [string, number]) {
  console.log(args);
}

joinNumAndString("a", 1);

参数也可以使用readonly进行修饰.

此外函数返回有void和never类型.前者表示没有返回值(或undefined)后者表示不会退出,常用于丢错误或循环.

函数重载

不同于其他语言重载,

有一些编程语言允许不同的函数参数,对应不同的函数实现。但是,JavaScript 函数只能有一个实现,必须在这个实现当中,处理不同的参数。因此,函数体内部就需要判断参数的类型及个数,并根据判断结果执行不同的操作。

function reverse(str: string): string;
function reverse(arr: any[]): any[];
function reverse(stringOrArray: string | any[]): string | any[] {
  if (typeof stringOrArray === "string")
    return stringOrArray.split("").reverse().join("");
  else return stringOrArray.slice().reverse();
}

重载声明的排序很重要,因为 TypeScript 是按照顺序进行检查的,一旦发现符合某个类型声明,就不再往下检查了,所以类型最宽的声明应该放在最后面,防止覆盖其他类型声明

构造函数

type AnimalConstructor = new () => Animal;

function create(c: AnimalConstructor): Animal {
  return new c();
}
create(Animal);

构造函数的类型写法,就是在参数列表前面加上new命令

此外也有对象形式写法

type F = {
  new (s: string): object;
}

针对对象,既可以使用type别名也可以使用interface

interface ReadOnlyPerson {
  readonly name: string;
  readonly age: number;
}

let w:ReadOnlyPerson = {
  name:"John",
  age: 22
}

空对象是 TypeScript 的一种特殊值,也是一种特殊类型。

TypeScript 不允许动态添加属性,所以对象不能分步生成,必须生成时一次性声明所有属性。

const obj = {};
obj.prop = 123; // 报错

因为Object可以接受各种类型的值,而空对象是Object类型的简写,所以它不会有严格字面量检查,赋值时总是允许多余的属性,只是不能读取这些属性。

interface Empty {}
const b: Empty = { myProp: 1, anotherProp: 2 }; // 正确
b.myProp; // 报错
let d: {};
// 等同于
// let d:Object;

d = {};
d = { x: 1 };
d = "hello";
d = 2;

interface 是对象的模板,可以看作是一种类型约定,中文译为“接口”。使用了某个模板的对象,就拥有了指定的类型结构。

interface Person {
  firstName: string;
  lastName: string;
  age: number;
}

interface 可以表示对象的各种语法,它的成员有 5 种形式。

  • 对象属性
  • 对象的属性索引
  • 对象方法
  • 函数
  • 构造函数

interface 与 type 的区别有下面几点。

(1)type能够表示非对象类型,而interface只能表示对象类型(包括数组、函数等)。

(2)interface可以继承其他类型,type不支持继承。

可以在interface中写方法以及利用interface写函数,构造函数.

// 写法一
interface A {
  f(x: boolean): string;
}

// 写法二
interface B {
  f: (x: boolean) => string;
}

// 写法三
interface C {
  f: { (x: boolean): string };
}

interface Add {
  (x: number, y: number): number;
}

const myAdd: Add = (x, y) => x + y;

interface ErrorConstructor {
  new (message?: string): Error;
}

interface可以实现继承,而type不行.而且可以多继承.多重继承时,如果多个父接口存在同名属性,那么这些同名属性不能有类型冲突,否则会报错

interface Shape {
  name: string;
}

interface Circle extends Shape {
  radius: number;
}

interface Style {
  color: string;
}

interface Shape {
  name: string;
}

interface Circle extends Style, Shape {
  radius: number;
}

type Country = {
  name: string;
  capital: string;
};

interface CountryWithPop extends Country {
  population: number;
}

注意,如果type命令定义的类型不是对象,interface 就无法继承

多个同名接口会进行合并.

interface Box {
  height: number;
  width: number;
}

interface Box {
  length: number;
}

举例来说,Web 网页开发经常会对windows对象和document对象添加自定义属性,但是 TypeScript 会报错,因为原始定义没有这些属性。解决方法就是把自定义属性写成 interface,合并进原始定义。

interface A {
  f(x: "foo"): boolean;
}

interface A {
  f(x: any): void;
}

// 等同于
interface A {
  f(x: "foo"): boolean;
  f(x: any): void;
}

如果两个 interface 组成的联合类型存在同名属性,那么该属性的类型也是联合类型

interface Circle {
  area: bigint;
}

interface Rectangle {
  area: number;
}

declare const s: Circle | Rectangle;

s.area; // bigint | number

对于顶层声明的属性,可以在声明时同时给出类型,如果不给声明默认any.

class Point {
  x: number;
  y: number;
}

TypeScript 有一个配置项strictPropertyInitialization,只要打开,就会检查属性是否设置了初值,如果没有就报错。

image-20240212174733858

如果打开了这个设置,但是某些情况下,不是在声明时赋值或在构造方法里面赋值,为了防止这个设置报错,可以使用非空断言。

class Point {
  x!: number;
  y!: number;
}

泛型类

class Box<Type> {
  contents: Type;

  constructor(value: Type) {
    this.contents = value;
  }
}

const b: Box<string> = new Box("hello!");
class Pair<K, V> {
  key: K;
  value: V;
}

抽象类

abstract class A {
  foo: number;
}

abstract class B extends A {
  bar: string;
}

抽象类的内部可以有已经实现好的属性和方法,也可以有还未实现的属性和方法。后者就叫做“抽象成员”(abstract member),即属性名和方法名有abstract关键字,表示该方法需要子类实现。如果子类没有实现抽象成员,就会报错。

泛型

function getFirst<Type>(arr: Type[]): Type {
  return arr[0];
}

不过为了方便,函数调用时,往往省略不写类型参数的值,让 TypeScript 自己推断,有些复杂的使用场景,TypeScript 可能推断不出类型参数的值,这时就必须显式给出.

类型参数的名字,可以随便取,但是必须为合法的标识符。习惯上,类型参数的第一个字符往往采用大写字母。一般会使用T(type 的第一个字母)作为类型参数的名字。如果有多个类型参数,则使用 T 后面的 U、V 等字母命名,各个参数之间使用逗号(“,”)分隔。

泛型主要用在四个场合:函数、接口、类和别名。

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

function id<T>(arg: T): T {
  return arg;
}
let myid: <T>(arg: T) => T = id;
interface Box<Type> {
  contents: Type;
}

let box: Box<string>;

类型别名

type Nullable<T> = T | undefined | null

type Container<T> = { value: T };
type Tree<T> = {
  value: T;
  left: Tree<T> | null;
  right: Tree<T> | null;
};

类型参数默认值

function getFirst_<T = string>(arr: T[]): T {
  return arr[0];
}

类型参数的约束条件

function comp<Type extends { length: number }>(a: Type, b: Type) {
  if (a.length > b.length) {
    return a;
  }
  return b;
}

type Fn<A extends string, B extends string = "world"> = [A, B];
type Result = Fn<"hello">

类型参数的约束条件如下

<TypeParameter extends ConstraintType>

泛型使用注意:

  1. 尽量少用泛型
  2. 类型参数越少越好
  3. 类型参数需要出现两次
  4. 泛型可以嵌套

Enum类型

enum Color {
  Red, // 0
  Green, // 1
  Blue, // 2
}
enum Direction {
  Up = "UP",
  Down = "DOWN",
  Left = "LEFT",
  Right = "RIGHT",
}

Enum 结构本身也是一种类型。比如,上例的变量c等于1,它的类型可以是 Color,也可以是number

多个同名的 Enum 结构会自动合并。

const enum MediaTypes {
  JSON = "application/json",
  XML = "application/xml",
}

const url = "localhost";

fetch(url, {
  headers: {
    Accept: MediaTypes.JSON,
  },
}).then((response) => {
  // ...
});

类型断言

// 语法一
let bar: T = <T>foo;

// 语法二
let bar: T = foo as T;

类型断言要求实际的类型与断言的类型兼容,实际类型可以断言为一个更加宽泛的类型(父类型),也可以断言为一个更加精确的类型(子类型),但不能断言为一个完全无关的类型

此外还有as const断言,s const断言只能用于字面量,as const也不能用于表达式

或者先断言为unknown.

expr as unknown as T;

对于那些可能为空的变量(即可能等于undefinednull),TypeScript 提供了非空断言,保证这些变量不会为空,写法是在变量名后面加上感叹号!

const root = document.getElementById("root")!;

断言函数

function isString(value: unknown): asserts value is string {
  if (typeof value !== "string") throw new Error("Not a string");
}

模块和namespace

TypeScript 模块除了支持所有 ES 模块的语法,特别之处在于允许输出和输入类型。

export type Bool = true | false;

模块加载方式有classic和Node,也就是Command js和ES6.

namespace 用来建立一个容器,内部的所有变量和函数,都必须在这个容器里面使用。

它出现在 ES 模块诞生之前,作为 TypeScript 自己的模块格式而发明的。但是,自从有了 ES 模块,官方已经不推荐使用 namespace 了。

namespace Utils {
  function isString(value: any) {
    return typeof value === "string";
  }

  // 正确
  isString("yes");
}

Utils.isString("no"); // 报错

如果要在命名空间以外使用内部成员,就必须为该成员加上export前缀,表示对外输出该成员

namespace Utility {
  export function log(msg: string) {
    console.log(msg);
  }
  export function error(msg: string) {
    console.error(msg);
  }
}

Utility.log("Call me");
Utility.error("maybe!");

装饰器

装饰器(Decorator)是一种语法结构,用来在定义时修改类(class)的行为。

在语法上,装饰器有如下几个特征。

(1)第一个字符(或者说前缀)是@,后面是一个表达式。

(2)@后面的表达式,必须是一个函数(或者执行后可以得到一个函数)。

(3)这个函数接受所修饰对象的一些相关值作为参数。

(4)这个函数要么不返回值,要么返回一个新对象取代所修饰的目标对象。

装饰器函数和装饰器方法

type Decorator = (
  value: DecoratedValue,
  context: {
    kind: string;
    name: string | symbol;
    addInitializer?(initializer: () => void): void;
    static?: boolean;
    private?: boolean;
    access: {
      get?(): unknown;
      set?(value: unknown): void;
    };
  }
) => void | ReplacementValue;


type ClassDecorator = (
  value: Function,
  context: {
    kind: "class";
    name: string | undefined;
    addInitializer(initializer: () => void): void;
  }
) => Function | void;
function countInstances(value: any, context: any) {
  let instanceCount = 0;

  const wrapper = function (...args: any[]) {
    instanceCount++;
    const instance = new value(...args);
    instance.count = instanceCount;
    return instance;
  } as unknown as typeof MyClass;

  wrapper.prototype = value.prototype; // A
  return wrapper;
}

@countInstances
class MyClass {}

const inst1 = new MyClass();
inst1 instanceof MyClass; // true
inst1.count; // 1

declare关键字

declare 关键字用来告诉编译器,某个类型是存在的,可以在当前文件中使用。

它的主要作用,就是让当前文件可以使用其他文件声明的类型。举例来说,自己的脚本使用外部库定义的函数,编译器会因为不知道外部函数的类型定义而报错,这时就可以在自己的脚本里面使用declare关键字,告诉编译器外部函数的类型。这样的话,编译单个脚本就不会因为使用了外部类型而报错。

declare 关键字可以描述以下类型。

  • 变量(const、let、var 命令声明)
  • type 或者 interface 命令声明的类型
  • class
  • enum
  • 函数(function)
  • 模块(module)
  • 命名空间(namespace)

declare let x: number;
declare function sayHello(name: string): void;

sayHello("张三");
declare class Animal {
  constructor(name: string);
  eat(): void;
  sleep(): void;
}
declare namespace AnimalLib {
  class Animal {
    constructor(name: string);
    eat(): void;
    sleep(): void;
  }

  type Animals = "Fish" | "Dog";
}

// 或者
declare module AnimalLib {
  class Animal {
    constructor(name: string);
    eat(): void;
    sleep(): void;
  }

  type Animals = "Fish" | "Dog";
}

d.ts类型声明文件

可以为每个模块脚本,定义一个.d.ts文件,把该脚本用到的类型定义都放在这个文件里面。但是,更方便的做法是为整个项目,定义一个大的.d.ts文件,在这个文件里面使用declare module定义每个模块脚本的类型

使用时,自己的脚本使用三斜杠命令,加载这个类型声明文件。

/// <reference path="node.d.ts"/>

如果没有上面这一行命令,自己的脚本使用外部模块时,就需要在脚本里面使用 declare 命令单独给出外部模块的类型。

单独使用的模块,一般会同时提供一个单独的类型声明文件(declaration file),把本模块的外部接口的所有类型都写在这个文件里面,便于模块使用者了解接口,也便于编译器检查使用者的用法是否正确。

类型声明文件里面只有类型代码,没有具体的代码实现。它的文件名一般为[模块名].d.ts的形式,其中的d表示 declaration(声明)

/// <reference path="node.d.ts"/>
import { test } from "./test";
declare let x: number;
x = 1;
console.log(x);
console.log(test);
let p: Post = { id: 1, title: "title", content: "content" };

// node.d.ts
interface Post {
  id: number;
  title: string;
  content: string;
}

最后推荐两个练习网站:

  • TypeHero
  • type-challenges/type-challenges: Collection of TypeScript type challenges with online judge (github.com)

参考资料

  1. https://typescript.p6p.net
  2. TypeScript: Handbook - The TypeScript Handbook (typescriptlang.org)

如有疑问,欢迎各位交流!

服务器配置
宝塔:宝塔服务器面板,一键全能部署及管理
云服务器:阿里云服务器
Vultr服务器
GPU服务器:Vast.ai

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Docker启动后怎样运行jar包文件

启动容器&#xff1a; docker run -it your-image-name /bin/bash 我们用ls查看文件&#xff0c;在我们进入容器时并没有看到jar包&#xff0c;我们需要将jar包复制到Docker容器中: docker cp /PATH/xxx.jar containerName:/tmp/workdir/xxx.jar 复制过后就能看到在对应路径…

USB-C 音频转接器工作原理介绍

Type-C音频转接器&#xff1a;引领未来视听新纪元 随着科技浪潮的推进&#xff0c;Type-C接口已逐渐成为电子设备的主流选择。其正反随意插、高速传输和强大功能等独特优势&#xff0c;使得Type-C接口在日常生活中的应用越来越广泛。而Type-C音频转接器&#xff0c;作为连接Ty…

第15届机械与航空航天工程国际会议 (ICMAE 2024) 即将召开!

2024年第15届机械与航空航天工程国际会议&#xff08;ICMAE 2024&#xff09;将于2024年7月17 日至20日在克罗地亚萨格勒布举行。近几十年来&#xff0c;机械与航空航天工程在机器人、汽车系统、工业自动化、太空探索等重点领域取得了显著进展。本次会议将汇聚行业内的专家、学…

牛刀小试 - C++ 学生信息管理系统

参考文档&#xff1a; C实现&#xff1a;学生管理系统&#xff08;详细解析&#xff09; 关于switch中的default里面的break是否可以省略这件事 需求要求&#xff1a; &#xff08;1&#xff09;增加记录 &#xff08;2&#xff09;查找记录 &#xff08;3&#xff09;删除…

linux ext3/ext4文件系统(part2 jbd2)

概述 jbd2&#xff08;journal block device 2&#xff09;是为块存储设计的 wal 机制&#xff0c;它为要写设备的buffer绑定了一个journal_head&#xff0c;这个journal_head与一个transaction绑定&#xff0c;随着事务状态的转移&#xff08;运行&#xff0c;生成日志&#…

智能工厂建设模式及解决方案供应商---万界星空科技

今天就聊聊企业智能工厂的打造&#xff0c;企业想实现数字化转型建立智能工厂&#xff0c;就需要先建设数字化车间&#xff0c;可以说数字化车间是建设智能工厂的重要一环&#xff0c;智能工厂的基础是数字化车间。 一、智能工厂特征&#xff1a; 1&#xff0c;智能系统集成…

【前端】前端三要素之BOM

写在前面&#xff1a;本文仅包含BOM内容&#xff0c;JavaScript传送门在这里&#xff0c;DOM传送门在这里。 本文内容是假期中刷的黑马Pink老师视频&#xff08;十分感谢Pink老师&#xff09;&#xff0c;原文保存在个人的GitLab中&#xff0c;如果需要写的网页内容信息等可以评…

如何更换过期的SSL证书?

SSL证书是保护网站安全的重要组成部分&#xff0c;它能在客户端和服务器之间建立数据传输加密通道&#xff0c;防止数据在传输过程中被泄露、劫持和窃听。但SSL证书也有有效期限&#xff0c;当SSL证书到期时&#xff0c;您需要及时更换它&#xff0c;以确保网站的安全性和可信度…

Spring相关注解

文章目录 Spring注解Bean1、Bean 概述2、Bean 的声明1&#xff09;搭配 Configuration2&#xff09;搭配 Component3&#xff09;搭配 ApplicationContext 3、Bean 的注入1&#xff09;NO&#xff08;主要关注这个&#xff09;【1】同一配置类【2】不同配置类 2&#xff09;BY_…

信奥一本通:1085:球弹跳高度的计算

这个题的点在于注意他求得是一共经过的米数&#xff0c;也就是下降起跳都算在里面&#xff0c;例如第一次下降20再起跳15就是一次循环的高度 #include <iostream> # include <iomanip> using namespace std; double h,c1,s; int main(){cin >> h;s h;while…

1902_野火FreeRTOS教程内核在STM32中用到的2个中断PENDSV和SYSTICK

1902_野火FreeRTOS教程内核在STM32中用到的2个中断PENDSV和SYSTICK 全部学习汇总&#xff1a; g_FreeRTOS: FreeRTOS学习笔记 (gitee.com) 上面是涉及到的源代码&#xff0c;而这次需要分析的就是78、79行的两个中断。首先&#xff0c;需要确认NVIC_SYSPRI2寄存器的作用。 进一…

MySQL篇—事务和隔离级别介绍

☘️博主介绍☘️&#xff1a; ✨又是一天没白过&#xff0c;我是奈斯&#xff0c;DBA一名✨ ✌✌️擅长Oracle、MySQL、SQLserver、Linux&#xff0c;也在积极的扩展IT方向的其他知识面✌✌️ ❣️❣️❣️大佬们都喜欢静静的看文章&#xff0c;并且也会默默的点赞收藏加关注❣…

程序员们的“不关机”现象:一种技术文化还是不良习惯?

文章目录 程序员们的“不关机”现象&#xff1a;一种技术文化还是不良习惯&#xff1f;引言程序员为何不爱关机&#xff1f;开发环境的冷启动成本持续集成与持续部署远程办公与全球协作运行中的服务与调试环境随时待命的紧急响应 长期开机是否会对硬件产生损害&#xff1f;最后…

Word第一课

文章目录 1. 文件格式1.1 如何显示文件扩展名1.2 Word文档格式的演变1.3 常见的Word文档格式 3. 文档属性理解文档属性查看文档属性 4. 显示比例方式一&#xff1a; 手动调整方式二&#xff1a; 自动调整 5. 视图、窗口视图 1. 文件格式 1.1 如何显示文件扩展名 文档格式指的…

2-IOC容器的初始化流程

IOC容器的初始化流程 AbstractApplicationContext.refresh() 准备BeanFactory&#xff08;DefaultListableBeanFactory&#xff09; 设置ClassLoader 设置Environment 扫描要放入容器的Bean&#xff0c;得到对应的BeanDefinition 注册BeanPostProcessor 处理国际化 处理事件…

vue+element (el-progress)标签 隐藏百分比(%) ,反向显示 ,自定义颜色, demo 复制粘贴拿去用

1 效果: 2 页面代码: <el-row :gutter"10" ><el-col :span"12"><el-card ><div class"fourqu"><div><span slot"title">{{推送任务TOP5}}</span></div></div><div class&…

Unity NavMesh 清除不可行走区域

通常场景中物体设置为static或Navigation Static后&#xff0c;打开Navigation使用默认设置烘焙NavMesh&#xff0c;模型顶部和底部会出现蓝色网格&#xff0c;但其中有部分属于不可能到达区域&#xff0c;如下图 本文介绍两种可去掉NavMesh中不需要网格的方法&#xff1a; 方…

K210基础实验——点亮LED灯

一、目的是点亮K210开发板左下角的LED0和LED1&#xff0c;LED0是红灯&#xff0c;LED1是绿灯&#xff0c;两颗LED灯都是低电平点亮&#xff0c;高电平熄灭。 二、这是原理图上的硬件连接&#xff0c;LED0连接的是IO0&#xff0c;LED1连接的是IO17。 三、在src目录下新建文件夹 …

适用于高云FPGA的JTAG

目标板卡&#xff1a;小梅哥芯海无涯GOWIN高云ACG525(GW5A-LV25UG324) 1.软件要求&#xff1a;必须用商业版&#xff0c;因为教育版(V1.9.9Beta-4 Education)不支持此封装的GW5A。商业版需要上网申请License&#xff0c;此处提供D4D853392AD8.lic文件&#xff08;此方法为临时…

开启智能互动新纪元——ChatGPT提示词工程的引领力

目录 提示词工程的引领力 高效利用ChatGPT提示词方法 提示词工程的引领力 近年来&#xff0c;随着人工智能技术的迅猛发展&#xff0c;ChatGPT提示词工程正逐渐崭露头角&#xff0c;为智能互动注入了新的活力。这一技术的引入&#xff0c;使得人机交流更加流畅、贴近用户需求&…