Giter Club home page Giter Club logo

typescript-tutorial's Introduction

TypeScript 开源教程,介绍基本概念和用法,面向初学者。

typescript-tutorial's People

Contributors

95cc avatar alex12306 avatar biubiubiu999 avatar blockmood avatar casyalex avatar cnwhy avatar cy920820 avatar eltociear avatar gaufung avatar hermiablog avatar hey-lee avatar jiuyehengxia avatar kiritaniayaka avatar leejunhui avatar leinad59 avatar lvlin-qiuyu avatar nextchentong avatar nocodeempire avatar ruanyf avatar songjinke avatar sr2k avatar thinkasany avatar tsong-lc avatar vikyd avatar weishenhong avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

typescript-tutorial's Issues

[疑问]类型断言Assert章中70行感觉描述错误 ‘等号右边的类型是左边类型的子类型,子类型可以赋值给父类型‘

原文

// 正确
const p1:{ x: number } =
  { x: 0, y: 0 } as { x: number; y: number };

上面示例中,两种类型断言都是正确的。第一种断言将类型改成与等号左边一致,第二种断言使得等号右边的类型是左边类型的子类型,子类型可以赋值给父类型,同时因为存在类型断言,就没有严格字面量检查了,所以不报错。


类型断言Assert章中70行 ‘等号右边的类型是左边类型的子类型‘ 是不是描述错误
感觉是等号左边类型是等号右边断言后类型的子集。

image

关于TypeScript 类型运算符部分的模板字符串的可引用类型问题

原文:
注意,模板字符串可以引用的类型一共6种,分别是 string、number、bigint、boolean、null、undefined。引用这6种以外的类型会报错。
事实上,经过我测试,引用这六种之外的枚举类型,不会报错,可以解析。
例子:
enum e2 {
a = 'a',
b = 'b'
}
type t = w ${e2} // "w a" | "w b"
故此,望改正。
你的读者
2024年3月19日

第17章「装饰器」第8小节「accessor 装饰器」关于 accessor 描述错误的问题

原文:

class C {
  accessor x = 1;
}

上面示例中,accessor修饰符等同于为属性x自动生成取值器和存值器,它们作用于私有属性x。也就是说,上面的代码等同于下面的代码。

class C {
  #x = 1;

  get x() {
    return this.#x;
  }

  set x(val) {
    this.#x = val;
  }
}

上述示例中,经过 accessor 修饰的 x 并不会转化为私有属性。

playground 链接

class C {
  accessor x = 1;
  accessor #y = 1;
}

const c = new C();

console.log(c.x);
console.log(c.y);
//            ^? 此处访问 c.y 会报错

第19章 关于补充声明Window全局对象属性的问题

阮老师您好。我是您的一名小读者。原文,在 ./docs/declare.md

interface window {

下面的示例是为 window 对象添加一个属性`myAppConfig`。

```typescript
export {};

declare global {
  interface window {
    myAppConfig: object;
  }
}

const config = window.myAppConfig;
```

declare global 里 interface 后面的 window 的首字母 w 似乎需要大写,才能让 TS 识别接口类型。我这边 TS 版本是5.3.2。不知道这算不算一个问题呢?

對象:最小可选属性规则一節問題

文件連結

原文

如果一个对象的所有属性都是可选的,会触发最小可选属性规则。

type Options = {
  a?:number;
  b?:number;
  c?:number;
};

const obj:Options = {
  d: 123 // 报错
};

上面示例中,类型Options是一个对象,它的所有属性都是可选的,这导致任何对象实际都符合Options类型。

为了避免这种情况,TypeScript 添加了最小可选属性规则,规定这时属于Options类型的对象,必须至少存在一个可选属性,不能所有可选属性都不存在。这就是为什么上例的myObj对象会报错的原因。

問題描述

原文示例會報錯的原因是 d 不存在於 Options 類型中,並不是因為 最小可选属性规则

Playground

type Options = {
    a?: number;
    b?: number;
    c?: number;
};


// 沒有錯誤
const obj1: Options = {}

declare function parseOption(options: Options): void

// 仍然報錯
parseOption({ a: 1, d: 1 })


// 沒有錯誤
parseOption({})

Symbol 包装类型的问题?

const sym1:symbol = Object(Symbol('tset'))

我发现这样写,并没有报错。但按文档而言,这样获取的是包装类型,小写的symbol类型是不正确的?这里是不是有问题

关于第4章,1.8节”没有声明类型的变量,被赋值为undefined或null,它们的类型会被推断为any” 的问题

这一小段有点问题,https://wangdoc.com/typescript/types#undefined-%E7%B1%BB%E5%9E%8Bnull-%E7%B1%BB%E5%9E%8B。
开启了strictNullChecks,const b = undefined 应该被推断为undefined类型,const d = null 应该推断为 null类型。

具体原因不懂,个人认为是因为const定义的变量不可修改,所以定义时就可以推断出类型。

1692602525185

TypeScript基本用法中的错别字

tsconfig.json

TypeScript 允许将tsc的编译参数,写在配置文件tsconfig.json。只要当前目录有这个文件,tsc就会自动读取,所以运行时可以不写参数。

$ tsc file1.js file2.js --outFile dist/app.js

应该为
$ tsc file1.ts file2.ts --outFile dist/app.js

6.5tsconfig.json

类型断言

大神,类型断言那一章,联合类型断言
const s1:number|string = 'hello'; const s2:number = s1 as number; // 报错

值实际是字符串断言成number会报错, 应该断言成字符串,或者用unkonwn中转一下断言成number
const s2:string= s1 as string; const s22: number = s1 as unknown as number

第9章《对象》第2小节可选属性中两种写法不完全等效

在教程中提到:
可选属性等同于允许赋值为undefined,下面两种写法是等效的。

但是我在实际操作中发现,教程中提到的两种写法不完全等效。为方便区分,我将User类型的两种写法修改为User1 和 User2.
type User1 = {
firstName: string;
lastName?: string;
};

// 不完全等同于
type User2 = {
firstName: string;
lastName: string|undefined;
};

//创建对象,类型为User1,对象字面量中仅包含firstName属性。 type 为User1 不会报错,因为lastName为可选属性
const user1 : User1 = {
firstName: "alan",
}

//type为User2 会报错,因为lastName 值可以为string或undefined,但是不可省略 ,即 "lastName" in user2 应当返回true
const user2 : User2 = {
firstName: "alan",
}

//允许如下方式定义类型为User2 的对象
const user3 : User2 = {
firstName: "alan",
lastName:undefined
}

第四章 类型系统-5.值类型

x y互相赋值的例子后,
原文:上面示例中,变量x属于子类型,变量y属于父类型。子类型x不能赋值为父类型y,但是反过来是可以的。

如果一定要让子类型可以赋值为父类型的值,就要用到类型断言(详见《类型断言》一章)。

这两处表述是否有误。

建议补充一节列举ts 不那么好用的地方

从我自己使用经验,我真的体会到ts有时候不那么好用,引入的问题比起要解决问题反而更麻烦,举几个例子

  1. nodejs 18 引入的fetch 没法很好的用ts标注,这个问题单 DefinitelyTyped/DefinitelyTyped#60924 说得很清楚: 还没人能完全搞清楚怎么标注fetch好, 所以目前变通方法都让人感觉很麻烦

The short version is that no one has implemented the types for fetch in this package yet. There are some ideas about how best to handle it but I don't know if there is actually a consensus among maintainers of this package. If you'd like to help with that, DT has good guidelines for getting started as a contributor, and I'm sure several people on this thread would be eager to review a MR.

  1. narrow 这个功能没法对object的key生效,参见这个问题单 microsoft/TypeScript#43284
    所以在js 本来很简单,遍历 Object key的代码在ts 反而变得很麻烦
let options = {
    foo: 'bar',
    bar: 'baz',
}

for (const [key, value] of process.argv) {
    if (key in options) {
        options[key] = value; // 报错,尽管我已经在if 里
    }
}

进一步数组的 reduce 方法标注就会变得很复杂,参见 https://stackoverflow.com/questions/52856496/typescript-object-keys-return-string

typescript 5.0.4 变量定义不赋值不会报错

老师,在实操您的 《TypeScript 基本用法》一章,中第一小节类型声明中:TypeScript 规定,变量只有赋值后才能使用,否则就会报错。在typescript 5.0.4版本中没有报错。
image

第 10 章 关于 interface 章节,接口合并小节中,对 document 添加自定义属性代码片段,编译不通过。

  • tsconfig.json 配置
{
    "compilerOptions": {
        "target": "ES2020",
        "module": "ES2020",
        "outDir": "dist",
        "strict": true,
    },
    "include": ["src/**/*.ts"],
    "exclude": ["node_modules"]
}
  • 原文描述

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

  • 代码片段
interface Document {
  foo: string;
}

document.foo = 'hello';
  • 编译报错信息
error TS2339: Property 'foo' does not exist on type 'Document'.

某些章节不显示

作者您好,首先感谢您的付出。
我在阅读过程中有一点疑惑,为什么某些doc目录下的md没有被加到chapters.yml,进而也没有显示在网站上,如react.md。
请问是有什么特殊考量吗?
谢谢。

intro.md 中可能的描述错误

“语言简介(intro.md)”中。
“上面示例中,例一的报错是因为变量一旦赋值了,就不允许再改变类型”,这段描述可能有问题。

变量的类型确定,应该是在变量声明的时候,而不是赋值的时候。

// 这段代码可以通过编译,因为在第一行 c 已经被推断为 any 类型(这只是我的猜测)
let c;
console.log(typeof c);
c = 1;
console.log(typeof c);
c = '1';
console.log(typeof c);

第四章类型系统2.2小节symbol和bigint类型包装对象问题

在第四章《类型系统》2.2小节最后一段话,描述symbol类型和bigint包装对象时,有如下描述:
上一小节说过,Symbol()和BigInt()这两个函数不能当作构造函数使用,所以没有办法直接获得 symbol 类型和 bigint 类型的包装对象,因此Symbol和BigInt这两个类型虽然存在,但是完全没有使用的理由。

这句话有点小小的错误。实际上,在javascript中,使用Object()方法传递一个symbol值返回的就是一个symbol类型的包装对象,传递一个bigint类型的值Object()函数返回的就是一个bigint类型的包装对象。

第15章模块

第15章模块中简介章有语言描述错误。
image
这里应该改为:
上面命令发现b.ts依赖a.ts,就会自动寻找a.ts,也将其同时编译,因此编译产物还是a.js和b.js两个文件。

关于 模块—简介 部分

关于 模块—简介 部分

$ tsc --outFile result.js b.ts
弄好文件之后,我运行了上面的命令,出现如下错误
Cannot compile modules using option 'outFile' unless the '--module' flag is 'amd' or 'system'.
之后我尝试指定值,amd 或 system
结果发现出现的代码无法直接在浏览器运行。
这是一个错误。
如果您认同我的想法,希望尽快改正,感谢您的文档,您的文档yyds

勘误

第4章第4小节 undefined 和 null 的特殊性
image

测试结果:
image

使用命令行ts-node,也是同样的报错
不知道是哪里出问题了,可能是官方更新了这个特殊的地方?

【建议】希望增加暗黑模式

现在白底晚上看太晃眼了,希望参考一下vue官网那种,可以切换暗黑模式,或者可以实现自动根据时间切换主题

第 15 章 “import type 语句” 小节,关于报错的描述有疑问,求指教。

tsconfig.json 配置

{
    "compilerOptions": {
        "target": "ES2020",
        "module": "ES2020",
        "outDir": "dist",
        "strict": true,
    },
    "include": ["src/**/*.ts"],
    "exclude": ["node_modules"]
}

原文描述

第二个方法是使用 import type 语句,这个语句只能输入类型,不能输入正常接口。

// 正确
import type { A } from './a';

// 报错
import type { a } from './a';

上面示例中,import type 输入类型A是正确的,但是输入正常接口a就会报错。

实测

正常引入第二个语句 import type { a } from './a'; 时不会报错, 作为类型使用时也能正常使用,作为非类型的值使用时才会报错。例如:

import type { a } from './2'
type C = typeof a //正常

import type { a } from './2'
let c = a //报错: "a" 是使用 "import type" 导入的,因此不能用作值。ts(1361)

关于 Enum 类型的编译结果疑问

原文:

Enum 结构的特别之处在于,它既是一种类型,也是一个值。绝大多数 TypeScript 语法都是类型语法,编译后会全部去除,但是 Enum 结构是一个值,编译后会变成 JavaScript 对象,留在代码中。

// 编译前
enum Color {
  Red,     // 0
  Green,   // 1
  Blue     // 2
}

// 编译后
let Color = {
  Red: 0,
  Green: 1,
  Blue: 2
};

然而,这里的 Color 符合文末的“反向映射”中的内容:

数值 Enum 存在反向映射,即可以通过成员值获得成员名。

TypeScript playground 的编译结果符合反向映射中的结果:

"use strict";
var Color;
(function (Color) {
    Color[Color["Red"] = 0] = "Red";
    Color[Color["Green"] = 1] = "Green";
    Color[Color["Blue"] = 2] = "Blue"; // 2
})(Color || (Color = {}));

所以前面的“编译后”内容是否可以认为是不准确的?

第 6 章 只读元组为元组的父类型的描述是否有失偏颇?

image

图中地址:点我跳转

这里的描述是否有失偏颇? 如果按照文档描述, 只读元组为元组的父类型,那么下面代码示例中的 y 赋值给 x 是没有任何问题的, 因为这就是父类型赋值给子类型,是可以赋值的.

同时我问了问 GPT,以下是 GPT 的回答

在 TypeScript 中,只读元组(ReadonlyTuple)不是元组(Tuple)的父类型。

元组(Tuple)和只读元组(ReadonlyTuple)是两种不同的类型,只读元组是通过 Readonly 关键字将元组变为只读的 Utilities 类型。

具体来说:

1. 元组(Tuple)表示一个已知元素数量和类型的数组,比如:[string, number]。元组可读可写。

2. 只读元组(ReadonlyTuple)是通过 Readonly<T> 工具类型将元组变为只读的,比如:Readonly<[string, number]>。只读元组不能被修改。

3. 两者之间不存在继承关系,只读元组不是元组的子类型或父类型。

4. 但是可以将元组赋值给只读元组,因为只读元组相比元组是更加严格的类型。

所以综上所述,在 TypeScript 中,只读元组(ReadonlyTuple)和元组(Tuple)是两种不同的类型,之间不存在继承关系,只读元组不是元组的父类型或子类型。

👑 [建议] 导航菜单栏的优化

🥰 需求描述 | Requirements description

当前菜单栏的部分不太方便,阅读到底部想切换想要的栏目还需拖回顶部。当然,是有点吹毛求疵了。不过我个人蛮重视有户体验的,仅作为建议。

🧐 解决方案 | Solution

类似 https://vitepress.dev/guide/what-is-vitepress ,左侧大栏目,右侧当前页的小标题(应该是当前最流行的 markdown 类布局,条理清晰)

🚑 其他信息 | Other information

ps:只是建议,如果改进了,万分感谢。还有搜索方案很棒。

tsc 命令中的tsc src/*.ts报错

# 编译 src 目录的所有 .ts 文件
$ tsc src/*.ts

tsc src/.ts这个命令能用吗,我试了使用tsc src/.ts会报错:

error TS6053: File 'src/*.ts' not found.
The file is in the program because:
Root file specified for compilation

類:1.4 存取器方法一節,建議補充

原文

(2)set方法的参数类型,必须兼容get方法的返回值类型,否则报错。

class C {
  _name = '';
  get name():string {
    return this._name;
  }
  set name(value:number) {
    this._name = value; // 报错
  }
}

上面示例中,get方法的返回值类型是字符串,与set方法参数类型不兼容,导致报错。

描述

在 TypeScript 5.1 中, getter 與 setter 的參數類型不再有兼容限制

更新說明

也就是說,以下的例子現在是合法的

class C {
    _name = '';
    get name(): string {
        return this._name;
    }
    set name(value: number) {
        this._name = String(value)
    }
}

第17章 装饰器 第9节中装饰器的执行顺序的装饰器应用描述问题

原文描述是

原型方法的装饰器首先应用,然后是静态属性和静态方法装饰器,接下来是实例属性装饰器,最后是类装饰器。

经过测试,使用 md 中的源码,增加了静态方法装饰器,使用在线的 playground,分别选择 5.0.4 / 5.2.2 运行测试

function d(str:string) {
  console.log(`评估 @d(): ${str}`);
  return (
    value:any, context:any
  ) => console.log(`应用 @d(): ${str}`);
}

function log(str:string) {
  console.log(str);
  return str;
}

@d('类装饰器')
class T {
  @d('静态属性装饰器')
  static staticField = log('静态属性值');

  @d('静态方法装饰器1')
  static fn1(){}

  @d('原型方法装饰器')
  [log('计算方法名')]() {}

  @d('实例属性装饰器')
  instanceField = log('实例属性值');

  @d('静态方法装饰器2')
  static fn2(){}
}

结果输出是

[LOG]: "评估 @d(): 类装饰器" 
[LOG]: "评估 @d(): 静态属性装饰器" 
[LOG]: "评估 @d(): 静态方法装饰器1" 
[LOG]: "评估 @d(): 原型方法装饰器" 
[LOG]: "计算方法名" 
[LOG]: "评估 @d(): 实例属性装饰器" 
[LOG]: "评估 @d(): 静态方法装饰器2" 
[LOG]: "应用 @d(): 静态方法装饰器1" 
[LOG]: "应用 @d(): 静态方法装饰器2" 
[LOG]: "应用 @d(): 原型方法装饰器" 
[LOG]: "应用 @d(): 静态属性装饰器" 
[LOG]: "应用 @d(): 实例属性装饰器" 
[LOG]: "应用 @d(): 类装饰器" 
[LOG]: "静态属性值" 

所以在5.x的版本下,结论应该是

静态方法装饰器首先应用,然后是原型方法的装饰器和静态属性装饰器,接下来是实例属性装饰器,最后是类装饰器。


而使用4.x的版本输出结果为,也与描述不符

[LOG]: "计算方法名" 
[LOG]: "静态属性值" 
[LOG]: "评估 @d(): 原型方法装饰器" 
[LOG]: "应用 @d(): 原型方法装饰器" 
[LOG]: "评估 @d(): 实例属性装饰器" 
[LOG]: "应用 @d(): 实例属性装饰器" 
[LOG]: "评估 @d(): 静态属性装饰器" 
[LOG]: "应用 @d(): 静态属性装饰器" 
[LOG]: "评估 @d(): 静态方法装饰器1" 
[LOG]: "应用 @d(): 静态方法装饰器1" 
[LOG]: "评估 @d(): 静态方法装饰器2" 
[LOG]: "应用 @d(): 静态方法装饰器2" 
[LOG]: "评估 @d(): 类装饰器" 
[LOG]: "应用 @d(): 类装饰器" 

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.