- ts没有静态类,也没有单例
- 对象赋值:
interface Pointlike {
x: number;
y: number;
}
interface Named {
name: string;
}
function printPoint(point: Pointlike) {
console.log("x = " + point.x + ", y = " + point.y);
}
function printName(x: Named) {
console.log("Hello, " + x.name);
}
const obj = {
x: 0,
y: 0,
name: "Origin",
};
printPoint(obj);
printName(obj);
obj里包含了Pointlike定义的x和y字段,所以printPoint不会报错。同理printName也不会报错。
同理下述也不会报错:
class Car {
drive() {
// hit the gas
}
}
class Golfer {
drive() {
// hit the ball far
}
}
// No error?
let w: Car = new Golfer();
- ts没有反射,但是js的
typeof
和instanceof
,仍然能获取到对象的类型,不过都是object类型。
1. 支持的类型
ts类型(小写) | C#类型 | 说明 |
---|---|---|
boolean | bool | |
number | int和float | |
bigint | long | |
string(“或’) | string | |
‘[]’(数组) | 等同[] | |
Array | List或int[] | |
Tuple | Tuple | |
enum | enum | |
unkNown | dynamic | dynamic的精简版 |
any | dynamic | |
void | void | 主要用在函数上,并不是很有用 |
null和undefined | null ??? | handbook说没啥用,是void的子类型 |
never | ?? | 是其他所有类型的子类型,标识异常或死循环等 |
object | ??? | 非基础类型,除number,stiring,boolean,symbol,null,undefined之外的类型 |
(function type) | 委托 | 见示例 |
示例:
let fullName:string ='Bob';
let age:number=37;
let height:bigint=666;
let sentense:string = 'hello,my ${fullName}';//也支持插值显示
//1.数组
let list:number[]=[1,2,3];
let list:Array<number>=[1,2,3];
//2.元组
let x:[string,number];
x=['hello',2];//correct
x=['hello','sss'];//error
通过索引访问,如x[0]代表第1个元素,x[2]则报错.
//3枚举
enum Color{
red,
green,
black
}
let c:Color=Color.red;
//4. unkNown 编写代码时不知道是个啥类型,C# dynamic的精简版,可以随便赋值,但是不能访问所属类型的方法。
//5. void
function wareUser():void{};
let unusable:void=undefined;
//6. object
declare function create(o: object | null): void;
create({ prop: 0 });//OK
create(null);//OK
create(42);
Argument of type '42' is not assignable to parameter of type 'object | null'.
create("string");
Argument of type '"string"' is not assignable to parameter of type 'object | null'.
create(false);
Argument of type 'false' is not assignable to parameter of type 'object | null'.
create(undefined);
Argument of type 'undefined' is not assignable to parameter of type 'object | null'.
//7. function type
let myAdd: (baseValue: number, increment: number) => number =function(x:number,y:number):number{return 4;}
1.1 类型转换
let someValue: unkNown = "this is a string";
let strLength: number = (someValue as string).length;//推荐
let strLength: number = (<string>someValue).length;
1.2 var let const
https://www.typescriptlang.org/docs/handbook/variable-declarations.html
最好不要使用var,const是let的一个扩充,不允许被再次赋值。
- var:在哪里都可以被访问,(containing function, module, namespace, or global scope - all which we’ll go over later on - regardless of the containing block)。并且可以被重复声明,不报错。如下,定义了两个i:
function sumMatrix(matrix: number[][]) {
var sum = 0;
for (var i = 0; i < matrix.length; i++) {
var currentRow = matrix[i];
for (var i = 0; i < currentRow.length; i++) {
sum += currentRow[i];
}
}
return sum;
}
即使声明了一百次,但指向同一个。
- let的作用域只限定在大括号内。在用之前必须先声明。但是也可以有以下写法,shadowing功能,最好别用:
function sumMatrix(matrix: number[][]) {
let sum = 0;
for (let i = 0; i < matrix.length; i++) {
var currentRow = matrix[i];
for (let i = 0; i < currentRow.length; i++) {
sum += currentRow[i];
}
}
return sum;
}
1.3解构
https://www.typescriptlang.org/docs/handbook/variable-declarations.html#destructuring
2.接口
https://www.typescriptlang.org/docs/handbook/interfaces.html
2.1接口用来约束
interface LabeledValue {
label: string;
color?:string;//可选字段,即myObj里不包含这个字段也不会报错
}
function printLabel(labeledobj: LabeledValue) {
console.log(labeledobj.label);
}
let myObj = { size: 10, label: "Size 10 Object" };
printLabel(myObj);
只读字段:
interface Point {
readonly x: number;
readonly y: number;
}
let p1: Point = { x: 10, y: 20 };//只有创建时可被赋值
p1.x = 5; // error! Cannot assign to 'x' because it is a read-only property.
只读的ReadonlyArray:
let a: number[] = [1, 2, 3, 4];
let ro: ReadonlyArray<number> = a;
ro[0] = 12; // error! Index signature in type 'readonly number[]' only permits reading.
ro.push(5); // error! Property 'push' does not exist on type 'readonly number[]'.
ro.length = 100; // error! Cannot assign to 'length' because it is a read-only property.
a = ro; // error! The type 'readonly number[]' is 'readonly' and cannot be assigned to the mutable type 'number[]'.
a = ro as number[];//正确
2.1.1额外的字段检查
interface SquareConfig {
color?: string|number;
width?: number;
}
function createSquare(config: SquareConfig): { color: string; area: number } {
return { color: config.color || "red", area: config.width ? config.width*config.width : 20 };
}
let mySquare = createSquare({ colour: "red", width: 100 });//这么写是不对的
let obj={ colour: "red", width: 100 };
createSquare(obj);//这么写可以
let mySquare = createSquare({ width: 100, opacity: 0.5 } as SquareConfig);//这么写也可以
但是这么写又是不对的:
let obj={ colour: "red", widthsssssssss: 100 };
createSquare(obj);//error
2.1.2 函数类型 Function Types
interface SearchFunc {
(source: string, subString: string): boolean;
}
let mySearch: SearchFunc;
mySearch = function (src: string, sub: string): boolean {
let result = src.search(sub);
return result > -1;
};
用接口定义方法的规范
2.2接口用来实现implements
interface ClockInterface {
currentTime: Date;
setTime(d: Date): void;
}
class Clock implements ClockInterface {
currentTime: Date = new Date();
setTime(d: Date) {
this.currentTime = d;
}
constructor(h: number, m: number) {}
}
interface Shape {
color: string;
}
interface Penstroke {
penWidth: number;
}
interface Square extends Shape, Penstroke {
sideLength: number;
}
let square = {} as Square;
square.color = "blue";
square.sideLength = 10;
square.penWidth = 5.0;
可以用let a= {} as Square
来new对象?
混合类型Hybrid Types
interface Counter {
(start: number): string;
interval: number;
reset(): void;
}
function getCounter(): Counter {
let counter = function (start: number) {} as Counter;
counter.interval = 123;
counter.reset = function () {};
return counter;
}
let c = getCounter();
c(10);
c.reset();
c.interval = 5.0;
2.3接口扩展某个类extends
class Control {
private state: any;
}
interface SelectableControl extends Control {
select(): void;
}
class Button extends Control implements SelectableControl {
select() {}
}
class TextBox extends Control {
select() {}
}
class ImageControl implements SelectableControl {
Class 'ImageControl' incorrectly implements interface 'SelectableControl'.
Types have separate declarations of a private property 'state'.
private state: any;
select() {}
}
那这个接口只能被这个类的子类实现。
2.Functions (方法)
https://www.typescriptlang.org/docs/handbook/functions.html
JS的写法
// 有名字的方法
function add(x, y) {
return x + y;
}
// 匿名方法
let myAdd = function (x, y) {
return x + y;
};
TS写法
function add(x: number, y: number): number {
return x + y;
}
let myAdd = function (x: number, y: number): number {
return x + y;
};
2.1可空参数和参数默认值
function buildName(firstName: string, lastName?: string) {
// ...
}
function buildName(firstName: string, lastName = "Smith") {
// ...
}
function buildName(firstName = "Will", lastName: string) {
return firstName + " " + lastName;
}
let result4 = buildName(undefined, "Adams"); // 都是string类型,不需要的话就手动设置为undefined
2.2可变参数
类似于C#的 params
function buildName(firstName: string, ...restOfName: string[]) {
return firstName + " " + restOfName.join(" ");
}
// employeeName will be "Joseph Samuel Lucas MacKinzie"
let employeeName = buildName("Joseph", "Samuel", "Lucas", "MacKinzie");
2.3This问题
- JS中的this指向的是调用方
//会报错
let deck = {
suits: ["hearts", "spades", "clubs", "diamonds"],
cards: Array(52),
createCardPicker: function () {
return function () {
let pickedCard = Math.floor(Math.random() * 52);
let pickedSuit = Math.floor(pickedCard / 13);
return { suit: this.suits[pickedSuit], card: pickedCard % 13 };
};
},
};
let cardPicker = deck.createCardPicker();
let pickedCard = cardPicker();
alert("card: " + pickedCard.card + " of " + pickedCard.suit);
调用方在let pickedCard = cardPicker();
,而这里没有在任何方法中,所以this指向的是window
,在严格模式下this会是undefined。
解决方法是使用箭头函数:ECMAScript 6:Arrow functions capture the this where the function is created rather than where it is invoked
createCardPicker: function () {
// NOTE: the line below is Now an arrow function, allowing us to capture 'this' right here
return () => {
let pickedCard = Math.floor(Math.random() * 52);
let pickedSuit = Math.floor(pickedCard / 13);
return { suit: this.suits[pickedSuit], card: pickedCard % 13 };
};
},
但是使用--noImplicitThis
进行编译时还会有问题,this是any,因为它来自对象内部的函数表达式。改为这样:
createCardPicker: function (this: Deck) {
return () => {
let pickedCard = Math.floor(Math.random() * 52);
let pickedSuit = Math.floor(pickedCard / 13);
return { suit: this.suits[pickedSuit], card: pickedCard % 13 };
};
},
现在ts就知道this是Deck类型了。下述写法表示this不能在方法中被使用:
function f(this: void) {
// make sure `this` is unusable in this standalone function
}
2.4重载
let suits = ["hearts", "spades", "clubs", "diamonds"];
function pickCard(x: { suit: string; card: number }[]): number;
function pickCard(x: number): { suit: string; card: number };
function pickCard(x: any): any {
// Check to see if we're working with an object/array
// if so, they gave us the deck and we'll pick the card
if (typeof x == "object") {
let pickedCard = Math.floor(Math.random() * x.length);
return pickedCard;
}
// Otherwise just let them pick the card
else if (typeof x == "number") {
let pickedSuit = Math.floor(x / 13);
return { suit: suits[pickedSuit], card: x % 13 };
}
}
let myDeck = [
{ suit: "diamonds", card: 2 },
{ suit: "spades", card: 10 },
{ suit: "hearts", card: 4 },
];
let pickedCard1 = myDeck[pickCard(myDeck)];
alert("card: " + pickedCard1.card + " of " + pickedCard1.suit);
let pickedCard2 = pickCard(15);
alert("card: " + pickedCard2.card + " of " + pickedCard2.suit);
let pickedCard2 = pickCard(true);//将报错 因为只接收array和number
3.Unions and Intersection Types
联合类型(交集类型)
let a:number;//atomic type
let a:number|boolean;//这就是union type
type t=|number|boolean;
let a:t;//a属于t类型中的某一种
并集类型(Intersection Types)
interface ErrorHandling {
success: boolean;
error?: { message: string };
}
interface ArtworksData {
artworks: { title: string }[];
}
interface ArtistsData {
artists: { name: string }[];
}
// These interfaces are composed to have
// consistent error handling, and their own data.
type ArtworksResponse = ArtworksData & ErrorHandling;
type ArtistsResponse = ArtistsData & ErrorHandling;
const handleArtistsResponse = (response: ArtistsResponse) => {
if (response.error) {
console.error(response.error.message);
return;
}
console.log(response.artists);
};
4. 类 Class
https://www.typescriptlang.org/docs/handbook/classes.html#classes
let p=new Person("name");//new一个对象
class Man extends Person{};//继承
同样也有多态:
let p:Person=new Man();
同样也支持public(默认)、private、protected
ECMAScript也有private,写法是#name:string
,ts写法是private name :string
,效果是一样的。
ts属于结构型系统(structural type system),比较两个对象a和b的type是否一致时,比较的是a和b的内部成员的生命是否都一样。但是当成员里有private 和 protected的时候,就不能这么简单比较了:
class Animal {
private name: string;
constructor(theName: string) {
this.name = theName;
}
}
class Rhino extends Animal {
constructor() {
super("Rhino");
}
}
class Employee {
private name: string;
constructor(theName: string) {
this.name = theName;
}
}
let animal = new Animal("Goat");
let rhino = new Rhino();
let employee = new Employee("Bob");
animal = rhino;//正确:因为共享同一个name
animal = employee;//错误:虽然都有name,但不是同一个
当protected修饰构造函数时,表示此类只能在子类内构造:
class Person {
protected name: string;
protected constructor(theName: string) {
this.name = theName;
}
}
// Employee can extend Person
class Employee extends Person {
private department: string;
constructor(name: string, department: string) {
super(name);
this.department = department;
}
public getElevatorPitch() {
return `Hello, my name is ${this.name} and I work in ${this.department}.`;
}
}
let howard = new Employee("Howard", "Sales");
let john = new Person("John");//错误
只读readonly:同C#,声明或者构造函数时赋值
构造参数上添加public、private、readonly:这样整个类中可直接使用,避免多一次定义
class Octopus {
readonly numberOfLegs: number = 8;
constructor(readonly name: string) {}
}
let dad = new Octopus("Man with the 8 strong legs");
dad.name;
给字段添加get set:set或get时做一些额外的处理,等同于C#的属性
const fullNameMaxLength = 10;
class Employee {
private _fullName: string = "";
get fullName(): string {
return this._fullName;
}
set fullName(newName: string) {
if (newName && newName.length > fullNameMaxLength) {
throw new Error("fullName has a max length of " + fullNameMaxLength);
}
this._fullName = newName;
}
}
let employee = new Employee();
employee.fullName = "Bob Smith";
if (employee.fullName) {
console.log(employee.fullName);
}
静态字段Static:同C#的static
抽象类Abstract:同C#的抽象类,子类不需要有override修饰。
5.枚举
enum Direction {
Up=1,//不指定的话,默认为0.
Down,
Left,
Right
}
枚举的赋值可以为number或string类型。
枚举的值也可以通过计算赋值:
enum FileAccess {
G = "123".length
}
6.泛型Generics
https://www.typescriptlang.org/docs/handbook/generics.html
同C#的泛型
泛型约束
如果要约束泛型的类型:
interface Lengthwise {
length: number;
}
function loggingIdentity<T extends Lengthwise>(arg: T): T {
console.log(arg.length); // Now we kNow it has a .length property, so no more error
return arg;
}
(T extends Lenghtwise就等同于C#的 where T: Lengthwise.
同理还有K extends keyof T
:K需要是T里面的一个key。
可以被new:
function create<T>(c: { new (): T }): T {
return new c();
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。