TypeScript,从0到入门带你进入类型的世界

简介: 该文章提供了TypeScript的入门指南,从安装配置到基础语法,再到高级特性如泛型、接口等的使用,帮助初学者快速掌握TypeScript的基本用法。

ts vs js

众所周知, js 是一门弱类型语言,并且规范较少。这就很容易导致在项目上线之前我们很难发现到它的错误,等到项目一上线,浑然不觉地, bugUpUp了。于是,在过去的这两年, ts 悄悄的崛起了。

周一随着一波热潮,也开始进入了 ts 的世界,不得不感叹 ts 的静态美。

下面的文章中将讲解我对 TS 入门的一些归纳总结。一起来了解一下吧!

一、什么是TypeScript?

1、编程语言的类型

动态类型语言(Dynamic Typed Language) 静态类型语言(Statically Typed Langeage)
JavaScript C,C++,C#,JAVA

2、TypeScript究竟是什么?

  • Typescript,即 Javascript that scales

  • ts 把不看重类型的动态语言 JS 转变成关注类型的静态语言

  • 可以说ts是静态类型风格的类型系统

  • es6es10 甚至是 esnext 的语法支持;

  • 兼容各种浏览器,各种系统,各种服务器,完全开源。

二、为什么要学习TypeScript?

1、程序更容易理解

动态语言存在函数或者方法中其输入输出的参数类型等问题,同时,动态语言还受到各种各样的约束,比如需要手动调试等等。那么有了 ts ,代码本身就可以解决上述问题了, ts 让程序更容易理解,程序理解我们,我们就可以少干很很多事情。

就像我们在与别人交谈时,假如我们逻辑很清晰的表达给对方,对方马上听懂了,并且理解了我们,我们也很省力,不用长篇大论的介绍。

2、效率更高

ts 可以在在不同的代码块和定义中进行跳转,并且代码有补全功能

同时, ts 还有丰富的接口提示,可以通过使用 . 来提示所有的接口内容。

3、更少的错误

ts编程期间,就可以发现大部分的错误。这样就可以杜绝掉一些比较常见的错误,也使得后面程序运行更加通畅。

4、非常好的包容性

ts 可以完全地兼容 Javascript ,同时,如果要引入像 JQuery 之类的第三方库时,可以单独编写类型文件来引入这些库。

5、一点小缺点

相比于 js 来讲, ts 在学习之初,需要去习惯一些规范,短期内会增加一点学习成本。但短期的学习成本增加将会使得在后期的开发当中减少很多不必要的错误和麻烦,间接的也为自己的开发带来很大的益处。

闲谈到此结束,让我们一起来进入 ts 的世界吧!

三、typescript入门

1、如何安装TypeScript

npm install -g typescript

2、查看版本号

tsc -v

四、Typescript数据类型

1、原始数据类型和Any类型

(1)原始数据类型

//定义一个布尔值数据
let isDone: boolean = false

//定义一个数字类型
let age: number = 20

//定义字符串类型
let firstName: string = 'monday'
let message: string = `Hello, ${
     firstName}`

//定义undefind和null类型
let u: undefined = undefined
let n: null = null

//给数字赋值undefid
let num: number = undefined

(2)Any 类型

如果我们有时候不能确定一个数据是什么类型的话,那么我们可以用any类型来定义。比如:

//定义一个any类型数据
let notSure: any = 4
notSure = 'maybe a string'
notSure = true

notSure.myName
notSure.getName()

2、数组和元组

(1)数组

//声明一个数字类型的数组
//注意:后面的数组只能传递数字,传递其他类型的数据都会报错
let arrOfNumbers: number[] = [1, 2, 3];
arrOfNumbers.push(3)

function test(){
   
    //arguments 为类数组
    console.log(arguments)
}

(2)元组

//确定一个元组里面的内容和数量,下面表示确定user这个元组必须且只能接收两个参数
//同时第一个属性必须是String类型,第二个属性是Number类型
let user: [String, Number] = ['abc', 13]

3、interface 接口

interface的定义:

  • 对象Object 的形状 (shape) 进行描述;
  • Duck Typing(鸭子类型)。

我们来看一段代码:

interface Person{
   
    // readonly表示只读状态
    readonly id: number,
    name: String,
    //加一个问号表示该参数可选可不选
    age?: number
}

let monday: Person = {
   
    id: 1,
    name: 'monday',
    age: 18
}

monday.id = 12323; //因为加了readonly,所以此时访问不了,会报错

4、function函数

function函数是什么:

  • JS 中,函数是一等公民。
  • 函数和其他类型的对象都一样,可以作为参数,可以存入数组,也可以被另外一个函数返回,可以被赋值给另外一个变量
  • 函数主要由两个部分组成:输入(传参)输出(返回结果)

我们来看个例子:

function add(x: number, y: number, z?: number): number{
   
    if(typeof z === 'number'){
   
        return x + y + z;
    }else{
   
        return x + y;
    }
}

let result = add(1, 2, 3);
console.log(result); //6

通过以上函数,我们实现了两个树或者三个树的相加操作。此时,需要我们注意的是,可选参数后面不能再添加不确定参数,否则程序就会发生混乱。比如:

function add(x: number, y: number, z?: number, t: number): number{
   
    if(typeof z === 'number'){
   
        return x + y + z;
    }else{
   
        return x + y;
    }
}

以上代码中的 t 是肯定不被允许添加的,因为前面已经有了可选参数 z ,而后面又突然健冒出来个 t ,想想都不太合理。


到这里,假设我们由一个新的变量名,名字叫 add2 。这个时候我们想要给它像 add 函数一样的类型。那么该怎么处理呢?

let add2: (x:number, y:number, z?: number) => number = add

注意上面这个箭头 => 不是 ES6 中的箭头函数,而是 ts 中声明函数类型返回值的方法。

上面这个语句中就说明了, add2 返回的值是一个 number 类型数值,并且让它等于 add 函数。同时,要记得的是,在 ts 当中,凡是在 : 后面都是声明在声明类型。


上面这样写好像有点冗余,我们来用 interface 来实现同样的效果。

在第3点的 interface 中我们了解到, interface 是对对象的形状进行描述,但值得注意的是, interface 也可以是对函数的形状进行描述。我们用代码来实现一下。

interface ISum {
   
    (x: number, y: number, z?: number) : number
}

let add2: ISum = add

通过以上代码,我们看到,用 interface 来封装一个函数的返回值来行,看起来优雅了不少。这里先体会一下, interface 的强大之处,在后面还会继续讲解。

5、类型推论、联合类型和类型断言

(1)类型推论

有时候我们还没有给一个数据定义类型,就直接给它赋值了。这个时候我们要怎么来判断呢。这个数据的类型呢?

比如:

let str = 123

当出现这样的情况时,编译器会直接给 str 赋上 number 类型。那么此时如果我们想这么干:

let str = 123
str = 'asd' //会报错

结果当然时不行的。当第一次赋值的时候,编译器就已经给 str 一个 number 类型,认定 str 就是 number 类型。而后我们还想要给 str 赋值上一个 string 类型的数据,肯定是会报错的。

(2)联合类型

有时候我们对一个数据的类型不够确定,比如说不知道某一个数据它是 number 类型还是 string 类型。这个时候我们就可以用联合类型来进行一波操作。

let numberOrString: number | string

通过这种方式,我们对我们所定义的属性 numberOrString 进行联合类型操作。

一般情况下,联合类型会结合类型断言来进行使用。接下来我们来讲类型断言。

(3)类型断言

1)TypeScript 不确定一个联合类型的变量到底是哪个类型的时候,我们只能访问此联合类型的所有类型中共有的属性或方法,而有时候呢,我们确实需要在还不确定类型的时候就访问其中一个类型特有的属性或方法。因此我们采用类型断言的方式将其指定为一个类型。(这么做只是先欺骗了 ts ,让其信任我们所指定的类型)

let str = 123
function getLength(input: string | number) : number{
   
    // 用as对input进行类型断言,先给input指定一个类型,后面判断不是再进行转换
    //注意:类型断言只做类型选择,而不做类型转换
    const str = input as string
    console.log(typeof str)
    if(str.length){
   
        return str.length
    }else{
   
        const number = input as number
        return number.toString().length
    }
}

2) 看到这里,已经开始感觉到类型断言的神奇之处。但用上面这种方法感觉好像还有一点点冗余,于是我们引入一个 type guard ,即类型守护。我们来看下实现方式。

let str = 123
function getLength2(input: string | number): number{
   
    if(typeof input === 'string'){
   
        return input.length
    }else{
   
        return input.toString().length
    }
}

五、Typescript中的类:class

js 中我们用了构造函数和原型链的方式来实现继承,同时在 ES6 中出现了 class 类继承的方法。那在 typescript 中呢,继承的方法又更加丰富了。让我们一起来一探究竟吧!

1、类的定义

我们先来看下类的定义。

(1)类(Class)

类定义了一切事物的抽象特点,包含它的属性和方法。比如:

class Animal{
   
    // 构造函数是实例化执行时候的逻辑
    constructor(name){
   
        this.name = name
    }
    run(){
   
        return `${
     this.name} is running`
    }
}

阅读以上代码我们可以知道,通过 class 可以定义一个

(2)对象(Object)

对象 Object ,就是类的实例举个例子: 🙆‍♂️

我们可以把类 class 比喻成一张蓝图,比如说汽车是一个 class ,那么它就像是一张造汽车的图纸。第二个是 ObjectObject 通过 new 生成,那么前面有了汽车的蓝图,我们现在就可以创造实实在在的汽车了。我们可以说一辆特斯拉是汽车的实例,也可以说宝马是汽车的另外一个实例。

同样我们用上面的例子来做衍生。具体如下:

class Animal{
   
    // 构造函数是实例化执行时候的逻辑
    constructor(name){
   
        this.name = name
    }
    run(){
   
        return `${
     this.name} is running`
    }
}
const snake = new Animal('lily')
console.log(snake.run())

阅读以上代码我们可以知道,我们定义了一个 snake ,这个 snake 继承了 Animal 类,因此它就可以用 Animal 类的属性方法

此时打印结果如下:

实例

(3)面向对象(OOP)的三大特性

面向对象的三大特性分别为:封装继承多态

  • 封装: 指将数据的操作细节隐藏起来,只暴露对外的接口。那这样子的话,对于外界的调用端来说,他们不需要也不可能知道细节,只能通过对外的接口来访问该对象。
  • 继承: 子类可以继承父类,子类除了拥有父类的所有特征外,还会拥有一些更具体的特性
  • 多态: 由继承产生的相关不同的类,对同一个方法可以有不同的响应。比如,猫和狗,他们都可以继承 Animal 类,但是他们分别实现 run() 方法,此时呢,针对某一个实例,我们无需了解它是猫还是狗,这个时候可以直接调用 run() ,程序会自动判断出来,应该如何去执行这个方法。

同样,我们用上面的代码做衍生,来看继承多态是怎么样的。


继承:

class Animal{
   
    // 构造函数是实例化执行时候的逻辑
    constructor(name){
   
        this.name = name
    }
    run(){
   
        return `${
     this.name} is running`
    }
}
const snake = new Animal('lily')
// console.log(snake.run())

class Dog extends Animal{
   
    bark(){
   
        return `${
     this.name} is barking`
    }
}

const xiaoqi = new Dog('xiaoqi')
console.log(xiaoqi.run())
console.log(xiaoqi.bark())

此时打印结果如下:

继承

从上面可以看到, Dog 继承了 Animal 类,此时 Dog 就拥有了 Animal 类的属性和方法。而 xiaoqi 实例化了 Dog ,因此它也拥有 Dog 的属性和方法。


多态:

class Animal{
   
    // 构造函数是实例化执行时候的逻辑
    constructor(name){
   
        this.name = name
    }
    run(){
   
        return `${
     this.name} is running`
    }
}
const snake = new Animal('lily')
// console.log(snake.run())
//-----------------------------------
class Dog extends Animal{
   
    bark(){
   
        return `${
     this.name} is barking`
    }
}

const xiaoqi = new Dog('xiaoqi')
console.log(xiaoqi.run())
console.log(xiaoqi.bark())
//-----------------------------------
class Cat extends Animal{
   
    // 静态方法不需要进行实例化,直接在类上调用即可
    static categories = ['mammal']
    constructor(name){
   
        super(name)
        console.log(this.name)
    }
    run(){
   
        return `Meow, ` + super.run() 
    }
}
const maomao = new Cat('maomao')
console.log(maomao.run())
// 直接访问静态属性
// 为什么要有静态属性?当定义和实例没有太大关系时,可以考虑使用静态方法实现
console.log(Cat.categories)

此时打印结果如下:

多态

阅读代码我们可以发现, xiaoqi 继承了 dogrun() 方法,而 Cat 继承了 Animal 类,但是它对 run() 方法进行了改写,因此最终的 run() 方法为改写后的效果。

所以, maomao 继承了 Cat 类,最后 maomao 调用 run() 方法时,就会调用 Cat 里面改写的 run() 方法,而不是 Animal 类的 run() 方法。

这样, xiaoqimaomao 虽然同样继承自 Animal 类,但他们调用 run() 方法的结果各自相互独立,如此,就实现了多态。

同时,我们还要注意一个点,就是静态属性。大家可以看到上面定义的 categories ,用了 static 来定义它为静态属性。当把变量定义为静态属性时,则当外部需要该静态方法时,不需要进行实例化,之类在类上调用即可。

那么问题来了,我们什么时候才需要有静态属性呢?

其实,当定义的内容和实例没有太大关系时,就可以考虑使用静态方法。比如常量的使用,常量基本是固定的,不会变的,所以我们可以考虑直接使用静态方法来获取它。

2、Typescript中的类

Typescript是通过什么方式来增强类的呢,typescript一般通过以下四种修饰符来增强类:

修饰符 含义
public 修饰的属性或方法是公有的
private 修饰的属性或方法是私有的
protected 修饰的属性或方法是受保护的
readonly 只能读不能写

有了以上这四种修饰符呢,我们就可以给类的方法和属性进行权限管理。为什么要做权限管理呢?因为总有些内容,我们是不愿意暴露给外部使用的,所以需要进行权限管理。

值得注意的是,对于 protected 这个修饰符来说,只有子类可以访问父类的属性和方法其他实例都不能访问。这其实可以把 protected 这个变量理解为遗产,父类的东西直接给子女继承,其余外部人员一概不能访问。

3、类和接口

(1)解决什么问题

继承存在着这样一个困境,在面向对象的世界中,一个类只能继承另外一个类,有时候同类之间有一些共同的特性,但是使用子类来继承父类又很难完成。于是接口就出现了。

(2)如何解决

类可以使用 implements 来实现接口,怎么做呢?我们可以把这些相同的特性提取成接口,然后用 implements 这个关键字来实现,这样就大大提高了面向对象的灵活性。

(3)举个例子

假如我们现在要让一辆汽车和一部手机来实现打开播放器的功能那么我们会这么实现:

class Car{
   
    switchRadio(trigger: boolean){
   

    }
}

class CellPhone{
   
    switchRadio(trigger: boolean){
   

    }
}

但是这样子看起来好像就没有特别雅观。于是我们可以写一个打开播放器的接口,然后用 implements 来实现这个功能。代码如下:

interface Radio{
   
    switchRadio(trigger: boolean): void
}

class Car implements Radio{
   
    switchRadio(trigger: boolean){
   

    }
}

class CellPhone implements Radio{
   
    switchRadio(trigger: boolean){
   

    }
}

这样,就让Car和CellPhone实现了打开播放器的功能。

接下来,我们继续写一个接口,可以实现检查电池电量的功能。并且让手机不仅可以打开播放器,还可以检查电池电量。代码如下:

interface Radio{
   
    switchRadio(trigger: boolean): void
}

interface Battery{
   
    checkBatteryStatus(): void
}

class Car implements Radio{
   
    switchRadio(trigger: boolean){
   

    }
}

class CellPhone implements Radio,Battery{
   
    switchRadio(trigger: boolean){
   

    }
    checkBatteryStatus(){
   

    }
}

阅读代码我们可以发现,我们要给继承两个接口 Radio,Battery ,这样看似乎还有点冗余。于是我们可以这样实现:

interface Radio{
   
    switchRadio(trigger: boolean): void
}

interface RadioWithBattery extends Radio{
   
    checkBatteryStatus(): void
}

class Car implements Radio{
   
    switchRadio(trigger: boolean){
   

    }
}

class CellPhone implements RadioWithBattery{
   
    switchRadio(trigger: boolean){
   

    }
    checkBatteryStatus(){
   

    }
}

通过 interface 继承 interface ,最终用 implement 去抽象和验证类的属性和方法,达到抽离功能的目的。

相信通过以上的简单了解,大家能感受到一点 interface 的奇妙之处。

六、枚举

1、普通枚举

枚举常使用于我们在程序中需要做权限管理或者做判断时等各种场景。枚举比较简单,下面直接用代码演示:

enum Direction{
   
    Up,
    Down,
    Left,
    Right
}

console.log(Direction.Up) //0
console.log(Direction.Down) //1
console.log(Direction.Left) //2
console.log(Direction.Right) //3
console.log(Direction[0]) //Up

除了以上基本用法外,我们还可以给枚举赋值:

enum Direction{
   
    Up = 10,
    Down,
    Left,
    Right
}

console.log(Direction.Up) //10

2、常量枚举

我们来定义一个常量,与 enum 做判断。

enum Direction{
   
    Up = 'Up',
    Down = 'Down',
    Left = 'Left',
    Right = 'Right'
}

//定义一个常量,直接与enum做判断
const value = 'Up';
if(value === Direction.Up){
   
    console.log('go Up!') // go Up!
}

使用常量枚举可以有效地提升性能,常量会内联枚举的任何用法,而不会把枚举变成任意的 Javascript 代码。

这样一说,那是不是所有的 enum 都可以使用常量枚举呢?答案自然是否定的。

枚举的值有两种类型,一种是常量值枚举(constant),一种是计算值枚举(computed)。只有常量值枚举可以进行常量枚举,而计算值枚举不能进行常量枚举

七、泛型

接下来我们来讲 TypeScript 中最难的一部分,泛型。

1、普通泛型

泛型,即 generics 。指在定义函数、接口或类的时候,我们不预先指定类型,而是在使用的时候再指定类型和其特征。

可以理解为,泛型就相当于一个占位符或者是一个变量,在使用时再动态的填入进去,填进去以后既可以来确定我们的类型值。

接下来我们用代码来演示一下:

function echo<T>(arg: T): T{
   
    return arg
}

const result = echo(true)
console.log(result) // true

我们通过 <> 来定义一个未知的泛型,之后当我们给它赋值时,就可以对应值的数据类型。


现在我们再用泛型来定义一个 number 类型的数组。具体代码如下:

// 早期定义一个number类型的数组
let arr: number[] = [1, 2, 3]
// 用泛型定义一个number类型的数组
let arrTwo: Array<number> = [1, 2, 3]

假如我们现在要调换两个元素的位置,那么用泛型我们可以这么实现。具体代码如下:

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

const result2 = swap(['abc', 123])
console.log(result2[0]) //123
console.log(result2[1]) //abc

通过泛型,我们就顺利调换了两个元素的位置。

2、约束泛型

在泛型中使用 extends 关键字,就可以让传入值满足我们特定的约束条件,而不是毫无理由的随意传入。

比如,我们想要让我们定义的内容是一个数组,我们可以这么处理。具体代码如下:

function echoWithArr<T>(arg: T[]): T[]{
   
    console.log(arg.length)
    return arg
}
const arrs = echoWithArr([1, 2, 3])

这样,就把 arrs 定义为一个数组。


假设我们现在想要让我们定义的内容可以访问到 length 方法,那么我们需要加一点佐料。具体代码如下:

interface IWithLength{
   
    length: number
}

function echoWithLength<T extends IWithLength>(arg: T): T{
   
    console.log(arg.length)
    return arg
}

const str = echoWithLength('str')
const obj = echoWithLength({
    length: 10, width: 20 })
const arr2 = echoWithLength([1, 2, 3])

通过 extends 关键字来继承特定的 interface ,使得我们定义的内容 strobjarr2 达到可以访问length方法的目的。

通过以上举例,我们可以知道,泛型可以用来灵活的约束参数的类型,参数不需要是个特别死板的类型,而可以通过我们的约束来达到我们想要的目的。

3、泛型在类和接口中的使用

(1)泛型在类中的使用

class Queue<T>{
   
    private data = []
    push(item: T){
   
        return this.data.push(item)
    }
    pop(): T{
   
        return this.data.shift()
    }
}
// 确定这是一个number类型的队列
const queue = new Queue<number>()
queue.push(1)
console.log(queue.pop().toFixed())

(2)泛型在接口中的使用

interface KeyPair<T, U>{
   
    key: T
    value: U
}
let kp1: KeyPair<number, string> = {
   key: 1, value: 'str'}
let kp2: KeyPair<string, number> = {
   key: 'str', value: 2}

通过以上代码演示可以发现,泛型就像是创建了一个拥有特定类型的容器,就仿佛给一个容器贴上标签一样。

八、类型别名

1、类型别名

类型别名,即 type aliase 。类型别名可以看作是一个快捷方式,可以把一个写起来很繁琐的类型创建一个简单的写法。比如:

//用以下这种写法,每次都要写一长串的(x: number, y: number) => number
let sum: (x: number, y: number) => number
const result = sum(1, 2)

//用type给类型进行别名
type PlusType = (x: number, y: number) => number
let sum2: PlusType
const result2 = sum2(2, 3)

//一个类型可以是字符串也可以是数字
type StrOrNumber = string | number
let result3: StrOrNumber = '123'
result3 = 123

2、字符串字面量

字符串字面量,指可以提供一系列非常方便使用的常量写法比如:

const str: 'name' = 'name'
const number: 1 = 1
type Direction = 'Up' | 'Down' | 'Left' | 'Right'
let toWhere: Direction = 'Left'

3、交叉类型

交叉类型,使用 type 这个扩展对象的一种方式。比如:

interface IName{
    name: string
}
type IPerson = IName & {age: number}
let person: IPerson = {name: 'monday', age: 18}

九、声明文件

我们在写ts时,难免会有遇到要引入第三方库的时候。这个时候就需要ts来做特殊处理。主要有以下两种做法:

1、 .d.ts 文件引入

假设我们要引入JQuery库来使用,那么我们可以在外部新增一个 JQuery.d.ts 文件,文件内代码如下:

declare var JQuery: (selector: string) => any;

之后便可以在我们定义的 ts 文件下引用 JQuery 相关库的内容。比如:

jQuery('#foo')

2、npm安装

我们也可以安装对应的第三方库的 npm 包。假如我们现在要引入一个 JQuery 库,那么我们可以这么处理。

npm install --save @type/jquery

十、内置类型

我们在写 ts 代码时,其实不知不觉已经使用了很多的内置对象。对象呢,是指根据标准(标准指 ECMADOM 等标准),在全局作用域 global 上面存在的对象。那我们在运行 tsc 时,这些内置的对象就会被当作附加的礼物给程序加载进行。接下来我们来体会一下几种常见的内置对象。

全局对象:

// global object 全局对象
const a: Array<number> = [1, 2, 3]
const date = new Date()
date.getTime()
const reg = /abc/
reg.test('abc')

内置对象:

// build-in object 内置对象
Math.pow(2, 2)

DOM和BOM对象:

// DOM 和 BOM
let body = document.body
let allLis = document.querySelectorAll('li')
allLis.keys()

document.addEventListener('click', e => {
   
    e.preventDefault()
})

功能性类型:

// Utility Types 功能性类型
interface IPerson{
   
    name: string
    age: number
}

let monday: IPerson = {
   name: 'monday', age: 20}

//可选属性
type IPartial = Partial<IPerson>
let monday2: Ipartial = {
   name: 'monday'}

//移除某一个属性
type Omit = Omit<IPerson, 'name'>
let monday3: Omit = {
   age: 20}

十一、结束语

关于 ts 的入门讲到这里就结束啦!希望大家能对 ts 有一个简单的认识!

如本文有不理解或有误的地方欢迎评论区评论或私信我交流!我们下期见!

  • 关注公众号 星期一研究室 ,不定期分享学习干货,学习路上不迷路~
  • 如果这篇文章对你有用,记得点个赞加个关注再走哦~
相关文章
|
10天前
|
弹性计算 人工智能 架构师
阿里云携手Altair共拓云上工业仿真新机遇
2024年9月12日,「2024 Altair 技术大会杭州站」成功召开,阿里云弹性计算产品运营与生态负责人何川,与Altair中国技术总监赵阳在会上联合发布了最新的“云上CAE一体机”。
阿里云携手Altair共拓云上工业仿真新机遇
|
6天前
|
机器学习/深度学习 算法 大数据
【BetterBench博士】2024 “华为杯”第二十一届中国研究生数学建模竞赛 选题分析
2024“华为杯”数学建模竞赛,对ABCDEF每个题进行详细的分析,涵盖风电场功率优化、WLAN网络吞吐量、磁性元件损耗建模、地理环境问题、高速公路应急车道启用和X射线脉冲星建模等多领域问题,解析了问题类型、专业和技能的需要。
2506 14
【BetterBench博士】2024 “华为杯”第二十一届中国研究生数学建模竞赛 选题分析
|
6天前
|
机器学习/深度学习 算法 数据可视化
【BetterBench博士】2024年中国研究生数学建模竞赛 C题:数据驱动下磁性元件的磁芯损耗建模 问题分析、数学模型、python 代码
2024年中国研究生数学建模竞赛C题聚焦磁性元件磁芯损耗建模。题目背景介绍了电能变换技术的发展与应用,强调磁性元件在功率变换器中的重要性。磁芯损耗受多种因素影响,现有模型难以精确预测。题目要求通过数据分析建立高精度磁芯损耗模型。具体任务包括励磁波形分类、修正斯坦麦茨方程、分析影响因素、构建预测模型及优化设计条件。涉及数据预处理、特征提取、机器学习及优化算法等技术。适合电气、材料、计算机等多个专业学生参与。
1519 14
【BetterBench博士】2024年中国研究生数学建模竞赛 C题:数据驱动下磁性元件的磁芯损耗建模 问题分析、数学模型、python 代码
|
8天前
|
编解码 JSON 自然语言处理
通义千问重磅开源Qwen2.5,性能超越Llama
击败Meta,阿里Qwen2.5再登全球开源大模型王座
530 13
|
1月前
|
运维 Cloud Native Devops
一线实战:运维人少,我们从 0 到 1 实践 DevOps 和云原生
上海经证科技有限公司为有效推进软件项目管理和开发工作,选择了阿里云云效作为 DevOps 解决方案。通过云效,实现了从 0 开始,到现在近百个微服务、数百条流水线与应用交付的全面覆盖,有效支撑了敏捷开发流程。
19282 30
|
1月前
|
人工智能 自然语言处理 搜索推荐
阿里云Elasticsearch AI搜索实践
本文介绍了阿里云 Elasticsearch 在AI 搜索方面的技术实践与探索。
18836 20
|
1月前
|
Rust Apache 对象存储
Apache Paimon V0.9最新进展
Apache Paimon V0.9 版本即将发布,此版本带来了多项新特性并解决了关键挑战。Paimon自2022年从Flink社区诞生以来迅速成长,已成为Apache顶级项目,并广泛应用于阿里集团内外的多家企业。
17524 13
Apache Paimon V0.9最新进展
|
8天前
|
人工智能 自动驾驶 机器人
吴泳铭:AI最大的想象力不在手机屏幕,而是改变物理世界
过去22个月,AI发展速度超过任何历史时期,但我们依然还处于AGI变革的早期。生成式AI最大的想象力,绝不是在手机屏幕上做一两个新的超级app,而是接管数字世界,改变物理世界。
458 48
吴泳铭:AI最大的想象力不在手机屏幕,而是改变物理世界
|
1天前
|
云安全 存储 运维
叮咚!您有一份六大必做安全操作清单,请查收
云安全态势管理(CSPM)开启免费试用
354 4
叮咚!您有一份六大必做安全操作清单,请查收
|
2天前
|
存储 关系型数据库 分布式数据库
GraphRAG:基于PolarDB+通义千问+LangChain的知识图谱+大模型最佳实践
本文介绍了如何使用PolarDB、通义千问和LangChain搭建GraphRAG系统,结合知识图谱和向量检索提升问答质量。通过实例展示了单独使用向量检索和图检索的局限性,并通过图+向量联合搜索增强了问答准确性。PolarDB支持AGE图引擎和pgvector插件,实现图数据和向量数据的统一存储与检索,提升了RAG系统的性能和效果。