编程技术文章分享与教程

网站首页 > 技术文章 正文

第二章、TS静态类型系统

hmc789 2024-11-18 12:58:54 技术文章 2 ℃

作者君吐槽:js本来就是个天马行空的写法,被ms加上高级语言的特性,强行加上了各种规则,损失了灵活性,学习理解成本也高,新人上手及用及出效果这种感觉炫不出来了,除开团队协助,代码重构容易点,不知道有什么玩意用。。。,但是感觉他确实有用,矛盾纠结中。

1.原语(Primitive)

参考资料:Primitive - MDN Web Docs Glossary: Definitions of Web-related terms | MDNMDN Web DocsMDN logoMozilla logo

参考资料:TypeScript: Documentation - Everyday Types (typescriptlang.org)

在JavaScript中,原语(primitive value, primitive data type )是指非对象且没有方法或属性的数据。有多种种基本数据类型:string、number、bigint、boolean、undefined、symbol、null, 每个在TypeScript中都有对应的类型,所有的原语都是不可变的;也就是说,它们不能被改变。重要的是不要将原语本身与赋给原语值的变量混淆。变量可以被重新赋值为一个新值,但是现有的值不能像对象、数组和函数那样被改变。该语言不提供改变原语值的实用程序。

原语没有方法,但仍然表现得像有方法一样。当在原语上访问属性时,JavaScript会将值自动装箱到包装器对象中,并访问该对象上的属性。例如, "foo".includes("f") 隐式地创建一个 String 包装器对象,并在该对象上调用String.prototype.includes() 。这种自动装箱行为在JavaScript代码中是不可观察到的

 In JavaScript, a primitive (primitive value, primitive data type) is data that is not an object and has no methods or properties. 
 
 All primitives are immutable; that is, they cannot be altered. It is important not to confuse a primitive itself with a variable assigned a primitive value. The variable may be reassigned to a new value, but the existing value can not be changed in the ways that objects, arrays, and functions can be altered. The language does not offer utilities to mutate primitive values.
 
 Primitives have no methods but still behave as if they do. When properties are accessed on primitives, JavaScript auto-boxes the value into a wrapper object and accesses the property on that object instead. For example, "foo".includes("f") implicitly creates a String wrapper object and calls String.prototype.includes() on that object. This auto-boxing behavior is not observable in JavaScript code but is a good mental model of various behaviors — for example, why "mutating" primitives does not work (because str.foo = 1 is not assigning to the property foo of str itself, but to an ephemeral wrapper object).
 # TypeScript 中的所有数字都是浮点数,支持十进制、十六进制、二进制和八进制字面量。
 let decLiteral: number = 6; // 十进制
 let hexLiteral: number = 0xf00d; // 十六进制
 let binaryLiteral: number = 0b1010; // 二进制
 let octalLiteral: number = 0o744; // 八进制
 
 const str: string = 'John';
 const num: number = 1;
 const bool: boolean = true;
 // const bigIntT1 = BigInt("1233333333333333333333333333333333");
 // 错误 TS2737: BigInt literals are not available when targeting lower than ES2020
 //  BigInt 字面量是在 ES2020 中引入的新特性,使用的 TypeScript 编译目标(target)版本低于 ES2020
 const bigIntT2: bigint = 1233333333333333333333333333333333n;
 
 //null 和 undefined 是所有类型的子类型,意味着你可以把 null 和 undefined 赋值给任何类型的变量。
 const nullT: null = null;
 const undefinedT: undefined = undefined;
 
 const sym1: symbol = Symbol();
 const sym2: symbol = Symbol('foo');
 const sym3: symbol = Symbol('foo');
 
 const typeString = typeof str;
 const typeNumber = typeof num;
 const typeBoolean = typeof bool;
 const typeBigInt = typeof bigIntT2;
 const typeNull = typeof nullT;
 const typeUndefined = typeof undefinedT;
 const typeSymbol = typeof sym2;
 
 console.log(`1.当前Primitive类型为:${typeString}`);
 console.log(`2.当前Primitive类型为:${typeNumber}`);
 console.log(`3.当前Primitive类型为:${typeBoolean}`);
 console.log(`4.当前Primitive类型为:${typeBigInt}`);
 console.log(`5.当前Primitive类型为:${typeNull}`);
 console.log(`6.当前Primitive类型为:${typeUndefined}`);
 console.log(`7.当前Primitive类型为:${typeSymbol}`);
 
 // 当编译目标是es2015,需要加上 @ts-expect-error 注解,目标2020,则不需要添加注解
 // @ts-expect-error
 console.log(`当前两个Symbol类型是否想的:${sym2 === sym3}`);
 console.log(Symbol.keyFor(Symbol.for('tokenString')) === 'tokenString');

2.数组类型([]):

可变数组,也写入Array<T>,使用类型后跟方括号 ([]) 表示数组元素的类型。或者使用 Array<elementType> 形式。

    let list1: number[] = [1, 2, 3];
    let list2: Array<number> = [1, 2, 3];
    let list3: any[] = [1,'',{}];

3.元组类型 (tuple):

元组允许表示一个已知元素数量和类型的数组,长度固定但可变

 let x: [string, number];
 x = ["hello", 10]; // OK

4.枚举类型 (enum):

枚举类型提供了一种有意义的方式来表达那些固定的数值集合。

 export enum AuthFlowEnum {
     /**
      * 查看
      */
     VIEW = 0,
     /**
      * 发起
      */
     START = 1,
     /**
      * 审批
      */
     AUDIT = 2,
 }
 const authFlow: AuthFlowEnum = AuthFlowEnum.VIEW;

5.任意类型 (any):

当你不确定一个值是什么类型的时候可以使用 any 类型,当你没有指定类型,而TypeScript又不能从上下文中推断类型时,编译器通常会默认为 any

 let notSure: any = 4;
 notSure = "maybe a string instead";
 notSure = false; // okay, definitely a boolean

6.never 类型:

表示永远不会出现的值,如抛出异常的函数返回值类型。

 function error(message: string): never {
    throw new Error(message);
 }

7.联合类型(Union Types)

联合类型 (union types): 一个值可以是几种类型之一。

 let age: number | string = 25;
 age = 'twenty five'; // OK
 age = 55;            // OK

8.交叉类型 (intersection types):

一个类型可以是多种类型的组合。

 interface A { a: string }
 interface B { b: string }
 type AB = A & B;
 let ab: AB = { a: 'a', b: 'b' };

9.类型别名(type aliases):

可以使用 type 关键字来创建一个新的类型名称,我们一直通过在类型注释中直接编写对象类型和联合类型来使用它们。 这很方便,但是经常需要多次使用相同的类型并通过单个名称引用它。实际上,您可以使用类型别名为任何类型命名,而不仅仅是对象类型。 例如,类型别名可以命名联合类型:

 type Point = {
   x: number;
   y: number;
 };
 // Exactly the same as the earlier example
 function printCoord(pt: Point) {
   console.log("The coordinate's x value is " + pt.x);
   console.log("The coordinate's y value is " + pt.y);
 }
 printCoord({ x: 100, y: 100 });
 //联合类型
 let age: number | string = 25;
 //用类型别名代替联合类型
 type ID = number | string;
 let age: ID = 25;

10.字面量类型:

字面量类型允许你使用具体的字符串或数字作为类型。

 let method: 'GET' | 'POST' = 'GET';
 // method = 'POST'; // OK
 // method = 'PUT';  // OK
 method = 'sdfdsf';  // error



Tags:

标签列表
最新留言