TypeScript是微軟開發的JavaScript的超集,TypeScript兼容JavaScript,能夠載入JavaScript代碼而後運行。javascript
TypeScript與JavaScript相比進步的地方 包括加入註釋,讓編譯器理解全部支持的對象和函數,編譯器會移出註釋,不會增長開銷,增長一個完整的類機構,使之更新是傳統的對象語言java
類 classes
接口interface
模塊 modules
node
仍是由於是node.js開發,咱們要安裝node的ts庫, 爲了強類型,主要仍是爲了智能感知。程序員
npm install @types/node --dev-save
複製代碼
npm install -g typescript
複製代碼
npm update -g typescript
tsc -v
新建一個文件夾 tstypees6
npm init -y
複製代碼
tsc --init
複製代碼
會建立一個這樣內容的tsconfig.jsontypescript
{
"compilerOptions": {
"module": "commonjs",
"target": "es6",
"removeComments": false,
"noImplicitAny": false,
"sourceMap": true,
"allowJs": true
},
"exclude": ["node_modules"]
}
複製代碼
由於寫node.js
你能夠修改target
爲es6
, 要調試把 sourceMap
改成true
, 添加allowjs
爲true
,就能夠ts和js混合用了.npm
初始化工程
npm init
tyc --init
ctrl + shift + b編譯,能夠選擇watch或者buildjson
首先咱們瞭解一下JavaScript的基本數據類型數組
var isBoon: boolean = false; // 必須給一個初始化的值
console.log(isBoon);
複製代碼
var num : number = 10;
console.log(num);
複製代碼
var str:string="iwen"
console.log(str);
複製代碼
let array1:Array<number>;
let array2:number[];
let array1:Array<number> = new Array<number>();
let array2:number[] = [1,2,3];
複製代碼
enum Color {Red,Green,Blue};
var colorName: String = Color[1]
console.log(colorName);
// 獲取枚舉類型的值
enum ColorVal { Red=1, Green=2, Blue=5 };
var colorName:String = ColorVal[5]
console.log(colorName);
// 經過val值去獲取key值
enum ColorKey { Red, Green, Blue}
var c:ColorKey = ColorKey.Green;
console.log(c);
// 獲取枚舉類型的下標
複製代碼
var notSure:any =10;
notSure="hello";
notSure=false
console.log(notSure);
// 獲得最後一次數據類型
複製代碼
// 必須是指定的返回值
function tell():string{
return "hello"
}
// 能夠沒有任何返回值的話
function tellNull():void {
}
複製代碼
在JavaScript中咱們學會了兩種參數bash
function add(x,y) {
return x+y;
}
複製代碼
var myAdd = function(x,y){
return x+y;
}
複製代碼
// 設置變量,包括返回值
function add(x: number, y: number): number {
return x+y;
}
// 註解模式寫法
var myAddts: (name: string, age: number)=>number=function(n:string,a:number):number{
return a;
}
複製代碼
增長❓後變成,能夠更變的值
function buildName(firstName:string,lastName?:string){
if (lastName) {
return `${firstName} ${lastName}`
}else{
return `${firstName}`
}
}
var name1 = buildName("ime","isee");
var name2 = buildName("im1")
複製代碼
function buildName2(firstName: string, lastName ="isee") {
if (lastName) {
return `${firstName} ${lastName}`
} else {
return `${firstName}`
}
}
var name3 = buildName2("im1");
var name4 = buildName2("ime", "isee");
複製代碼
function peopleName(firstName:string,...restOfname:string[]) {
return firstName + "" + restOfname.join(" ")
}
複製代碼
var people ={
name:['iwen','ime','if','bean'],
getName:function(){
return ()=>{
var i = Math.floor(Math.random()*4)
return {
n:this.name[i]
}
}
}
}
複製代碼
var people ={
name:['iwen','ime','if','bean'],
getName:()=>{
return ()=>{
var i = Math.floor(Math.random()*4)
return {
n:this.name[i]
}
}
}
}
複製代碼
function attr(name:string):string; function attr(age: number): number; function attr(nameorage: any): any{
if (nameorage){
console.log(nameorage);
}
}
attr("姓名")
複製代碼
class Person{
name:string;
age:number;
constructor(name:string,age:number) {
this.name = name;
this.age = age;
}
print(){
return this.name+":"+this.age
}
}
var p = new Person("a",12);
p.print();
複製代碼
class Student extends Person{
school: string;
constructor(school: string) {
super('ime', 800); // 繼承人類這個屬性
this.school = school;
}
tell(){
return this.name + ":" + this.age + this.school;
}
}
var s = new Student("學校");
s.tell();
複製代碼
關於類中成員訪問修飾符:
ts類中成員(成員屬性、成員方法)的訪問修飾符,相似於java中類成員的訪問修飾符,不一樣的是ts中默認是被public修飾。
public :公有 在當前類裏面、 子類 、類外面均可以訪問
protected:保護類型 在當前類裏面、子類裏面能夠訪問 ,在類外部無法訪問
private :私有 在當前類裏面能夠訪問,子類、類外部都無法訪問
class People{
private name:string; // 私有
public age:number; // 公有
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
print(){
return this.name+":"+this.age
}
}
複製代碼
class Student extends People{
constructor() {
super('ads',200);
}
tell(){
return "222";
}
}
var s = new Student();
s.age = 12;
// s.name = 12; 此時是沒法調用私有變量的
s.print();
console.log(s.print());
複製代碼
class Hello{
private _name:string;
constructor() {
this._name= _name
}
set name(name:string){
this._name = name
}
get name():string{
return this.name
}
tell(){
return this._name;
}
}
var h = new Hello();
h.name='iwen';
console.log(h.tell());
複製代碼
class Greeter{
greeting:string;
constructor(message:string) {
this.greeting = message
}
greet(){
return 'Hello,'+this.greeting;
}
}
var green:Greeter;
green=new Greeter('iwen');
console.log(green.greet());
複製代碼
**咱們先定義個接口,而後把符合接口定義的對象傳進去,這樣能提升代碼可讀性。 **
須要注意的是:
若是咱們不給傳進去的對象指定是接口類型的數據,那麼傳入的對象參數能夠包含其餘屬性,編譯器只會檢查那些必需的屬性是否存在,而且其類型是否匹配。
若是咱們給對象指定是接口類型的數據,那麼,對象的屬性必須和定義好的接口的必要屬性一致。必要屬性不能多也不能少。
function printeLabel(labelObj:{lable:string}) {
console.log(labelObj.lable);
}
var myObj = { lable:"Hello"}
printeLabel(myObj);
複製代碼
interface LabelValue{
label:string
}
function printeLabel(labelObj:LabelValue) {
console.log(labelObj.label);
}
var myObj = {label:"Hello-1"};
printeLabel(myObj)
複製代碼
在實際應用中,接口裏的屬性不全都是必需的。 有些是隻在某些條件下存在,或者根本不存在。在這種個狀況下能夠是用接口的可選屬性去定義。
以下代碼所示,name和age被定義爲可選屬性,那麼在傳對象的時候name和age就無關緊要。
interface USB{
name:string;
age?:number;
}
function printUSB(pu:USB){
console.log(pu.name);
console.log(pu.age);
}
var my = { name: "ime"}
printUSB(my)
複製代碼
若是咱們但願對象屬性只能在對象剛剛建立的時候修改其值。 咱們能夠在屬性名前用 readonly來指定只讀屬性。
interface Point{
readonly x:number;
readonly y:number;
}
function getPoint(p:Point){
console.log(p.x);
console.log(p.y);
}
let point:Point={x:1,y:2};
// point.x=2;//錯誤 這裏不能再子修改值
getPoint(point);
複製代碼
只讀數組也同樣,一旦定義後不能再修改數組
let a:ReadonlyArray<number> =[1,2,3,4,5];
// a[0]=2;//不能再修改該數組
// a.length=20;
複製代碼
接口能夠描述javascript的任何對象,不只能描述對象的屬性類型,固然也能描述對象的函數類型。
以下代碼所示,接口描述了這個函數的參數類型和返回值類型
interface SearchFunc{
/*在這裏咱們描述了這個接口有個函數 這個函數傳進去2個string類型的參數 而後返回一個boolean類型的數據*/
(source:string,subString:string):boolean
}
var mySearch: SearchFunc;
mySearch = function (source: string, subString: string){
var result = source.search(subString);
if (result!=-1) {
return true
}
else{
return false
}
}
複製代碼
跟接口描述函數類型差很少,咱們也能夠描述那些可以「經過索引獲得」的類型,好比經過下標獲取數組中的值 a[2];須要注意的是,索引器的類型只能爲 number 或者 string。
interface StringArray{
/*描述的一個數組 這個數組裏面的元素是string類型 而且只能經過number類型來索引 [index:number]是索引器 string [index:number]:string; // age:number; //須要注意的是,當咱們將這個接口是數組類型時,那麼,接口中定義的其它屬性的類型都必須是該數組的元素類型。 這裏的number類型是報錯的 } var myArray: StringArray; myArray=['iwen','ime']; console.log(myArray[1]) 複製代碼
所謂類類型,就是一個類去實現接口,而不是直接把接口拿來用,這更符合咱們的使用習慣。
interface IClock{
/*定義了一個接口 這個接口中有一個屬性和一個方法*/
currentTime:Date;
getTime(d:Date);
}
/*Time類實現IClock接口*/
class Time implements IClock{
currentTime:Date;
getTime(d:Date){
this.currentTime=d;
}
}
複製代碼
在TypeScript中,接口跟類同樣是能夠相互繼承的, 這讓咱們可以從一個接口裏複製成員到另外一個接口裏,能夠更靈活地將接口分割到可重用的模塊裏。
/*接口能夠繼承接口 而且能夠多繼承*/
interface shape{
color:string;
}
interface pen extends shape{
width:number;
}
let circle=<pen>{};//注意這裏的寫法,建立一個對象並指定泛型 circle.color="red";//這裏能夠獲取color屬性 circle.width=2;//有width屬性 複製代碼
/*接口能夠繼承接口 而且能夠多繼承*/
interface shape{
color:string;
}
interface pen extends shape{
width:number;
}
interface Circle extends shape,pen{
point:number[];
}
let c=<Circle>{};//注意這裏的寫法,建立一個對象並指定泛型 c.point=[1,2]; c.color="red"; c.width=1; 複製代碼
所謂的混合類型就是在一個接口中定義多種類型,好比屬性,函數,數組等。
interface Counter {
(start: number): string;
interval: number;
reset(): void;
}
function getCounter(): Counter {
let counter = <Counter>function (start: number) { }; counter.interval = 123; counter.reset = function () { }; return counter; } let c = getCounter(); c(10); c.reset(); 複製代碼
泛型就是在編譯期間不肯定方法的類型(普遍之意思),在方法調用時,由程序員指定泛型具體指向什麼類型
在代碼的過程當中,有些時候不肯定要傳什麼類型的參數,可是又但願被校驗
function Hello<T>(arg:T):T{
return arg;
}
var output = Hello<string>("Hello ime");
複製代碼
function Hello<T>(str:T[]):T[] {
console.log(str.length);
return str
}
var list:Array<string> = Hello<string>(['1','2','3'])
for (let i = 0; i < list.length; i++) {
console.log(list[i]);
}
複製代碼
class GetMin<T>{
arr:T[]=[];
add(ele:T){
this.arr.push(ele);
}
min():T{
var min=this.arr[0];
this.arr.forEach(function (value) {
if(value<min){
min=value;
}
});
return min;
}
}
var gm1= new GetMin<number>();
gm1.add(5);
gm1.add(3);
gm1.add(2);
gm1.add(9);
console.log(gm1.min());
var gm2= new GetMin<string>();
gm2.add("tom");
gm2.add("jerry");
gm2.add("jack");
gm2.add("sunny");
console.log(gm2.min());
複製代碼
interface ConfigFn{
<T>(value:T):T;
}
var getData:ConfigFn=function<T>(value:T):T{
return value;
}
getData<string>('張三');
// getData<string>(1243); //錯誤
// 相似 Map<String,Object> Param 接口
interface Param{
[index:string]:any
}
複製代碼
默認狀況下,當你開始在一個新的 TypeScript 文件中寫下代碼時,它處於全局命名空間中。如在 foo.ts
裏的如下代碼:
const foo = 123;
複製代碼
若是你在相同的項目裏建立了一個新的文件 bar.ts
,TypeScript 類型系統將會容許你使用變量 foo
,就好像它在全局可用同樣:
const bar = foo; // allowed
複製代碼
毋庸置疑,使用全局變量空間是危險的,由於它會與文件內的代碼命名衝突。咱們推薦使用下文中將要提到的文件模塊。
它也被稱爲外部模塊。若是在你的 TypeScript 文件的根級別位置含有 import
或者 export
,它會在這個文件中建立一個本地的做用域。所以,咱們須要把上文 foo.ts
改爲以下方式(注意 export
用法)
export const foo = 123;
複製代碼
在全局命名空間裏,咱們再也不有 foo
,這能夠經過建立一個新文件 bar.ts
來證實:
const bar = foo; // ERROR: "cannot find name 'foo'"
複製代碼
若是你想在 bar.ts
裏使用來自 foo.ts
的內容,你必須顯式導入它,更新 bar.ts
以下所示:
import { foo } from './foo';
const bar = foo; // allow
複製代碼
在 bar.ts
文件裏使用 import
,不但容許你使用從其餘文件導入的內容,並且它會將此文件 bar.ts
標記爲一個模塊,文件內定義的聲明也不會污染全局命名空間。
export
關鍵字導出一個變量(或者類型):// foo.ts
export const someVar = 123;
export type someType = {
foo: string;
};
複製代碼
export
的寫法除了上面這樣,還有另一種:// foo.ts
const someVar = 123;
type someType = {
type: string;
};
export { someVar, someType };
複製代碼
// foo.ts
const someVar = 123;
export { someVar as aDifferentName };
複製代碼
import
關鍵字導入一個變量或者是一個類型:// bar.ts
import { someVar, someType } from './foo';
複製代碼
// bar.ts
import { someVar as aDifferentName } from './foo';
複製代碼
// bar.ts
import * as foo from './foo';
// 你可使用 `foo.someVar` 和 `foo.someType` 以及其餘任何從 `foo` 導出的變量或者類型
複製代碼
import 'core-js'; // 一個普通的 polyfill 庫
複製代碼
export * from './foo';
複製代碼
export { someVar } from './foo';
複製代碼
export { someVar as aDifferentName } from './foo';
複製代碼
我並不喜歡用默認導出,雖然有默認導出的語法:
export default
let/const/var
);// some var
export default (someVar = 123);
// some function
export default function someFunction() {}
// some class
export default class someClass {}
複製代碼
import someName from 'someModule'
語法(你能夠根據須要爲導入命名):import someLocalNameForThisFile from './foo';
複製代碼
大體上和es6一致