目录
undefined和null类型
打开 strictNullChecks 功能,可以帮助我们发现bug。
//条件判断法
function doSomething(x: string | null) {
if (x === null) {
// do nothing
} else {
console.log("Hello, " + x.toUpperCase());
}
}
//非空断言操作符
function liveDangerously(x?: number | null) {
// No error
console.log(x!.toFixed());
}
boolean,number,bigint,string,symbol,object类型
类型名称首字母正常小写。
boolean
number
bigint
string
symbol
object
联合类型
类型1 | 类型2 | 类型N..
any类型
any类型为JS支持的任意类型,等同于 :
联合(union)类型 object|class|array|symbol|string|bigint|number|boolean|null|undefined
如果没有定义一个类型,编译器无法推断您的类型,编译器会默认赋予any类型。
let obj: any;
unknown类型
unknown类型类似于any类型,但更安全,所有类型的值可赋值给unknown类型,但unknown的值只可以赋值给unknown自己或any类型。
如果unknown没有首先断言或缩小到更具体的类型,则不允许对unknown进行任何操作。
function f1(a: any) {
a.b(); // OK
}
function f2(a: unknown) {
a.b();
Object is of type 'unknown'.
}
void返回类型
函数没有return语句或有return语句但没有显式返回值或隐式返回undefined值,使用void返回类型。
// The inferred return type is void
function noop() {
return;
}
never返回类型
never 是一种表示没有返回的返回类型。函数抛出异常或终止执行时,使用never返回类型。
function fail(msg: string): never {
throw new Error(msg);
}
字面量类型
let x: "hello" = "hello";
// OK
x = "hello";
// “howdy”类型不能赋值给“hello”类型。
x = "howdy";
一个只能有一个值的类型没有多大用处!
但是通过将文字组合成并集,您可以表达一个更有用的概念——例如,函数只接受特定的一组已知值:
function printText(s: string, alignment: "left" | "right" | "center") {
// ...
}
// OK
printText("Hello, world", "left");
// 类型 '"centre"' 实参不能赋值给类型 '"left" | "right" | "center"' 的形参.
printText("G'day, mate", "centre");
类型断言
有时候您知道关于值的类型信息,但是typescript不知道的情况下, 可以使用类型断言。
//方式一(推荐)
const myCanvas = document.getElementById("main_canvas") as HTMLCanvasElement;
//方式二(在.tsx会冲突,一般不推荐)
const myCanvas = <HTMLCanvasElement>document.getElementById("main_canvas");
TypeScript只允许类型断言转换为更特定或更不特定的类型版本。
const x = "hello" as number;
//Conversion of type 'string' to type 'number' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.
字面量类型断言
// @errors: 2345
declare function handleRequest(url: string, method: "GET" | "POST"): void;
// ---cut---
const req = { url: "https://example.com", method: "GET" };
handleRequest(req.url, req.method);
Argument of type 'string' is not assignable to parameter of type '"GET" | "POST"'.
//解决方案一
// Change 1:
const req = { url: "https://example.com", method: "GET" as "GET" };
// Change 2
handleRequest(req.url, req.method as "GET");
//解决方案二
const req = { url: "https://example.com", method: "GET" } as const;
handleRequest(req.url, req.method);
变量
let 变量名?[: 类型注解] = 值;
常量
const 常量名[: 类型注解] = 值;
函数
function name(参数名[: 类型注解])[: 返回类型注解] {
statements;
}
方法重写
一个派生类的方法必须遵循基类的方法契约。
class Base {
greet() {
console.log("Hello, world!");
}
}
class Derived extends Base {
// Make this parameter required
greet(name: string) {
Property 'greet' in type 'Derived' is not assignable to the same property in base type 'Base'.
Type '(name: string) => void' is not assignable to type '() => void'.
console.log(`Hello, ${name.toUpperCase()}`);
}
}
数组
let arr = 类型[element0, element1, ..., elementN];
//示例
number[]
string[]
元组
function doSomething(pair: [string, number]) {
const a = pair[0];
const a: string
const b = pair[1];
const b: number
// ...
}
doSomething(["hello", 42]);
对象
可以把对象字面量创建法创建的对象直接作为类型注解。属性之间可以用 , 或 ; 分隔。
// The parameter's type annotation is an object type
function printCoord(pt: { x: number; y: number }) {
console.log("The coordinate's x value is " + pt.x);
console.log("The coordinate's y value is " + pt.y);
}
printCoord({ x: 3, y: 7 });
类
字段可以用readonly修饰符为前缀,限制只可以构造函数为该字段赋值,防止构造函数之外的函数给该字段赋值。
class Greeter {
readonly name: string = "world";
constructor(otherName?: string) {
if (otherName !== undefined) {
this.name = otherName;
}
}
err() {
this.name = "not ok";
Cannot assign to 'name' because it is a read-only property.
}
}
const g = new Greeter();
g.name = "also not ok";
Cannot assign to 'name' because it is a read-only property.
类静态成员
class MyClass {
static x = 0;
static printX() {
console.log(MyClass.x);
}
}
console.log(MyClass.x);
MyClass.printX();
类成员访问控制
public:默认的访问可见性。
protected:只对子类可见,子类的对象不可显式访问。
private:只有基类自己可见。
抽象类
类、方法、字段可以是抽象的。
abstract class Base {
abstract getName(): string;
printName() {
console.log("Hello, " + this.getName());
}
}
const b = new Base();
接口
可以使用接口为任何类型命名,而不仅仅是对象类型。
//对象类型接口
interface Point {
x: number;
y: number;
}
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 });
//方法类型接口
interface Checkable {
check(name: string): boolean;
}
接口继承
接口既可以通过继承添加属性,又可以通过打开一个已经存在的接口添加属性。
//接口:继承添加属性
interface Animal {
name: string
}
interface Bear extends Animal {
honey: boolean
}
//接口:打开一个已经存在的接口添加属性
interface Window {
title: string
}
interface Window {
ts: TypeScriptAPI
}
实现接口
类可以实现多个接口,比如class C implements A, B {
.
interface Pingable {
ping(): void;
}
class Sonar implements Pingable {
ping() {
console.log("ping!");
}
}
class Ball implements Pingable {
Class 'Ball' incorrectly implements interface 'Pingable'.
Property 'ping' is missing in type 'Ball' but required in type 'Pingable'.
pong() {
console.log("pong!");
}
}
泛型
//泛型函数
function firstElement<Type>(arr: Type[]): Type | undefined {
return arr[0];
}
//泛型数组
Array<number>
//泛型类
class Box<Type> {
contents: Type;
constructor(value: Type) {
this.contents = value;
}
}
const b = new Box("hello!");
//泛型接口
interface Box<Type> {
contents: Type;
}
原创文章,作者:huoxiaoqiang,如若转载,请注明出处:https://www.huoxiaoqiang.com/javascript/javascriptlang/10209.html