目前公司的主架構已經定爲了react和typescript,所以把typescript又大體捋了一下react
我發現把正確的寫法和錯誤的寫法對比着來看.好像學習起來更加快速.更加有勁~web
正確的大部分人都會寫,咱們更重要的就是記住爲何錯了~typescript
至少這種方法對我很是有用,好了,廢話很少說.立刻開始~數組
JavaScript 的類型分爲兩種:原始數據類型和對象類型。tomcat
原始數據類型包括:布爾值、數值、字符串、null
、undefined
以及 ES6 中的新類型 Symbol
bash
本節主要介紹前五種原始數據類型在 TypeScript 中的應用。架構
布爾值是最基礎的數據類型,在 TypeScript 中,使用 boolean
定義布爾值類型:函數
如下都編譯經過的,而且給出了說明,一句話總結,是什麼類型就要賦值給什麼類型,這句話夠俗了吧學習
➖➖➖➖➖➖➖➖➖布爾➖➖➖➖➖➖➖➖➖
// 布爾值
let isDone: boolean = false;
// 事實上 `new Boolean()` 返回的是一個 `Boolean` 對象
let createdByNewBoolean: Boolean = new Boolean(1);
//(直接調用 `Boolean` 也能夠返回一個 `boolean` 類型)
let createdByBoolean: boolean = Boolean(1);
➖➖➖➖➖➖➖➖➖數值➖➖➖➖➖➖➖➖➖
// 數值
let decLiteral: number = 6;
let hexLiteral: number = 0xf00d;
// ES6 中的二進制表示法
let binaryLiteral: number = 0b1010;
// ES6 中的八進制表示法
let octalLiteral: number = 0o744;
let notANumber: number = NaN;
let infinityNumber: number = Infinity;
➖➖➖➖➖➖➖➖➖字符串➖➖➖➖➖➖➖➖➖
let myName: string = 'Tom';
➖➖➖➖➖➖➖➖➖空值➖➖➖➖➖➖➖➖➖
// 沒有返回值的函數爲void
function alertName(): void {
alert('My name is Tom');
}
//聲明一個 void 類型的只能將它賦值爲 undefined 和 null
let unusable: void = undefined;
➖➖➖➖➖➖➖➖➖Null 和 Undefined➖➖➖➖➖➖➖➖➖
// undefined 類型的變量只能被賦值爲 undefined,null 類型的變量只能被賦值爲 null
let u: undefined = undefined;
let n: null = null;
複製代碼
注意:正確的很好記,大多數人都會寫正確的,關鍵是要記住這些錯誤的!!!ui
➖➖➖➖➖➖➖➖➖布爾➖➖➖➖➖➖➖➖➖
// 注意,使用構造函數 `Boolean` 創造的對象不是布爾值
let createdByNewBoolean: boolean = new Boolean(1);❌
➖➖➖➖➖➖➖➖➖數值➖➖➖➖➖➖➖➖➖
let decLiteral: number = "6";❌
➖➖➖➖➖➖➖➖➖字符串➖➖➖➖➖➖➖➖➖
let myName: string = 999;❌
➖➖➖➖➖➖➖➖➖空值➖➖➖➖➖➖➖➖➖
// 沒有返回值的函數爲void
function alertName(): void {❌
return 666;
}
//聲明一個 void 類型的只能將它賦值爲 undefined 和 null
let unusable: void = 'I love you';❌
➖➖➖➖➖➖➖➖➖Null 和 Undefined➖➖➖➖➖➖➖➖➖
// undefined 類型的變量只能被賦值爲 undefined,null 類型的變量只能被賦值爲 null
let u: undefined = 888;❌
let n: null = 999;❌
複製代碼
// 顧名思義,能夠被任何值賦值
let anyThing: any = 'hello';
let anyThing: any = 888;
let anyThing: any = true;
let anyThing: any = null;
let anyThing: any = undefined;
// 變量若是在聲明的時候,未指定其類型,那麼它會被識別爲任意值類型:
let any;
any =true;
複製代碼
沒有錯誤的寫法~
// 若是沒有明確的指定類型,那麼 TypeScript 會依照類型推論(Type Inference)的規則推斷出一個類型。
let myFavoriteNumber = 'seven'; 等價於 let myFavoriteNumber :string= 'seven';
複製代碼
// 第一句已經被推論爲String類型了
let myFavoriteNumber = 'seven';
myFavoriteNumber = 7;❌
複製代碼
// 聯合類型(Union Types)表示取值能夠爲多種類型中的一種。
// 當你容許某個變量被賦值多種類型的時候,使用聯合類型,管道符進行鏈接
let myFavoriteNumber: string | number;
myFavoriteNumber = 'seven';
myFavoriteNumber = 7;
// 也可用於方法的參數定義, 都有toString方法,訪問 string 和 number 的共有屬性是沒問題的
function getString(something: string | number): string {
return something.toString();
}
複製代碼
// number類型沒有length屬性.因此編譯錯誤,由於咱們只能訪問此聯合類型的全部類型裏共有的屬性或方法:
function getLength(something: string | number): number {❌
return something.length;
}
複製代碼
// 賦值的時候,變量的形狀必須和接口的形狀保持一致(不能多也不能少,類型還必須一致)
interface Person {
name: string;
age: number;
}
let tom: Person = {
name: 'Tom',
age: 25
};
IUserInfo{
age : any;//定義一個任何變量的 age.
userName :string;//定義一個 username.
}
function getUserInfo(user : IUserInfo):string{
return user.age+"======"+user.userName;
}
➖➖➖➖➖➖➖➖➖可選屬性➖➖➖➖➖➖➖➖➖
interface Person {
name: string;
age?: number; // 表示這個屬性無關緊要
}
let tom: Person = {
name: 'Tom'
};
➖➖➖➖➖➖➖➖➖任意屬性➖➖➖➖➖➖➖➖➖
//但願一個接口容許有任意的屬性,可使用以下方式:旦定義了任意屬性,那麼肯定屬性和可選屬性的類型都必須是它的類型的子集
interface Person {
name: string;
age?: number;
[propName: string]: any;
}
let tom: Person = {
name: 'Tom',
gender: 'male' // 能夠加其餘的屬性
};
➖➖➖➖➖➖➖➖➖只讀屬性➖➖➖➖➖➖➖➖➖
interface Person {
readonly id: number; //
name: string;
age?: number;
[propName: string]: any;
}
let tom: Person = {
id: 89757, // 只讀
name: 'Tom',
gender: 'male'
};
複製代碼
// 一旦定義了任意屬性,那麼肯定屬性和可選屬性的類型都必須是它的類型的子集
interface Person {
name: string;
age?: number;
[propName: string]: string;
}
let tom: Person = {
name: 'Tom',
age: 25,
gender: 'male'❌
};
上例中,任意屬性的值容許是 string,可是可選屬性 age 的值倒是 number,number 不是 string 的子屬性,因此報錯了。
➖➖➖➖➖➖➖➖➖只讀屬性➖➖➖➖➖➖➖➖➖
interface Person {
readonly id: number;
name: string;
age?: number;
[propName: string]: any;
}
let tom: Person = {
name: 'Tom',
gender: 'male'
};
tom.id = 89757; // 不能被二次賦值❌
複製代碼
let fibonacci: number[] = [1, 1, 2, 3, 5];
let fibonacci: Array<number> = [1, 1, 2, 3, 5];
➖➖➖➖➖➖➖➖➖用接口表示數組➖➖➖➖➖➖➖➖➖
interface NumberArray {
[index: number]: number;
}
let fibonacci: NumberArray = [1, 1, 2, 3, 5];
➖➖➖➖➖➖➖➖➖any 在數組中的應用➖➖➖➖➖➖➖➖➖
let list: any[] = ['Xcat Liu', 25, { website: 'http://xcatliu.com' }];
➖➖➖➖➖➖➖➖➖類數組➖➖➖➖➖➖➖➖➖
function sum() {
let args: IArguments = arguments;
}
複製代碼
// 數組的項中不容許出現其餘的類型:
let fibonacci: number[] = [1, '1', 2, 3, 5];❌
// push 方法只容許傳入 number 類型的參數,可是卻傳了一個 string 類型的參數,因此報錯了。
let fibonacci: number[] = [1, 1, 2, 3, 5];
fibonacci.push('8');❌
// 類數組(Array-like Object)不是數組類型,好比 arguments
function sum() {❌
let args: number[] = arguments;
}
複製代碼
// 須要把輸入和輸出都考慮到
function sum(x: number, y: number): number {
return x + y;
}
➖➖➖➖➖➖➖➖➖函數表達式➖➖➖➖➖➖➖➖➖
let mySum = function (x: number, y: number): number {
return x + y;
};
// 不要混淆了 TypeScript 中的 => 和 ES6 中的 =>
let mySum: (x: number, y: number) => number = function (x: number, y: number): number {
return x + y;
};
➖➖➖➖➖➖➖➖➖接口定義函數的形狀➖➖➖➖➖➖➖➖➖
interface SearchFunc {
(source: string, subString: string): boolean;
}
let mySearch: SearchFunc;
mySearch = function(source, subString) {
return source.search(subString) !== -1;
}
➖➖➖➖➖➖➖➖➖可選參數➖➖➖➖➖➖➖➖➖
function buildName(firstName: string, lastName?: string) {
if (lastName) {
return firstName + ' ' + lastName;
} else {
return firstName;
}
}
let tomcat = buildName('Tom', 'Cat');
let tom = buildName('Tom');
➖➖➖➖➖➖➖➖➖參數默認值➖➖➖➖➖➖➖➖➖
function buildName(firstName: string, lastName: string = 'Cat') {
return firstName + ' ' + lastName;
}
➖➖➖➖➖➖➖➖➖剩餘參數➖➖➖➖➖➖➖➖➖
// rest 參數只能是最後一個參數,關於 rest 參數,是一個數組
function push(array: any[], ...items: any[]) {
items.forEach(function(item) {
array.push(item);
});
}
let a = [];
push(a, 1, 2, 3);
複製代碼
// 輸入多餘的(或者少於要求的)參數,是不被容許的:
function sum(x: number, y: number): number {
return x + y;
}
sum(1, 2, 3); ❌
sum(1);❌
// 輸入多餘的(或者少於要求的)參數,是不被容許的:
function sum(x: number, y: number): number {
return x + y;
}
sum(1, 2, 3);
// 可選參數後面不容許再出現必須參數了:
function buildName(firstName?: string, lastName: string) {❌
if (firstName) {
return firstName + ' ' + lastName;
} else {
return lastName;
}
}
let tomcat = buildName('Tom', 'Cat');
let tom = buildName(undefined, 'Tom');
複製代碼
// 可使用類型斷言,將 something 斷言成 string
function getLength(something: string | number): number {
if ((<string>something).length) {
return (<string>something).length;
} else {
return something.toString().length;
}
}
複製代碼
// 只能訪問此聯合類型的全部類型裏共有的屬性或方法
function getLength(something: string | number): number { ❌
return something.length;
}
複製代碼
// 使用 type 建立類型別名,類型別名經常使用於聯合類型
type Name = string;
type NameResolver = () => string;
type NameOrResolver = Name | NameResolver;
function getName(n: NameOrResolver): Name {
if (typeof n === 'string') {
return n;
} else {
return n();
}
}
複製代碼
// 枚舉(Enum)類型用於取值被限定在必定範圍內的場景,好比一週只能有七天
// 枚舉就是枚舉值到枚舉名進行反向映射
enum Days {Sun, Mon, Tue, Wed, Thu, Fri, Sat};
console.log(Days["Sun"]); // 0
console.log(Days[0]); // 'Sun'
enum Days {Sun = 7, Mon = 1, Tue, Wed, Thu, Fri, Sat};
console.log(Days["Sun"]); // 7
複製代碼
➖➖➖➖➖➖➖➖➖類➖➖➖➖➖➖➖➖➖
class Animal {
constructor(name) {
this.name = name;
}
sayHi() {
return `My name is ${this.name}`;
}
}
let a = new Animal('Jack');
console.log(a.sayHi()); // My name is Jack
➖➖➖➖➖➖➖➖➖繼承➖➖➖➖➖➖➖➖➖
class Cat extends Animal {
constructor(name) {
super(name); // 調用父類的 constructor(name)
console.log(this.name);
}
sayHi() {
return 'Meow, ' + super.sayHi(); // 調用父類的 sayHi()
}
}
let c = new Cat('Tom'); // Tom
console.log(c.sayHi()); // Meow, My name is Tom
➖➖➖➖➖➖➖➖➖存儲器➖➖➖➖➖➖➖➖➖
class Animal {
constructor(name) {
this.name = name;
}
get name() {
return 'Jack';
}
set name(value) {
console.log('setter: ' + value);
this.name = value;
}
}
let a = new Animal('Kitty'); // setter: Kitty
a.name = 'Tom'; // setter: Tom
console.log(a.name); // Jack
➖➖➖➖➖➖➖➖➖靜態方法➖➖➖➖➖➖➖➖➖
class Animal {
static isAnimal(a) {
return a instanceof Animal;
}
}
let a = new Animal('Jack');
Animal.isAnimal(a); // true
// 只能經過類名調用
a.isAnimal(a); // TypeError: a.isAnimal is not a function ❌
➖➖➖➖➖➖➖➖➖抽象類➖➖➖➖➖➖➖➖➖
abstract class Animal {
abstract makeSound():void
move():void {
console.log('roaming the earch...')
}
}
// 子類必須實現抽象類的抽象方法
複製代碼
public
修飾的屬性或方法是公有的,能夠在任何地方被訪問到,默認全部的屬性和方法都是 public
的
private
修飾的屬性或方法是私有的,不能在聲明它的類的外部訪問
protected
修飾的屬性或方法是受保護的,它和 private
相似,區別是它在子類中也是容許被訪問的
泛型就是解決 類 接口 方法的複用性、以及對不特定數據類型的支持
//只能返回string類型的數據
function getData(value:string):string{
return value;
}
//同時返回 string類型 和number類型 (代碼冗餘)
function getData1(value:string):string{
return value;
}
function getData2(value:number):number{
return value;
}
>>>>>>>>>>使用泛型後就能夠解決這個問題
// T表示泛型,具體什麼類型是調用這個方法的時候決定的
// 表示參數是什麼類型就返回什麼類型~~~
function getData<T>(value:T):T{
return value;
}
getData<number>(123);
getData<string>('1214231');
// 定義接口
interface ConfigFn{
<T>(value:T):T;
}
var getData:ConfigFn=function<T>(value:T):T{
return value;
}
getData<string>('張三');
getData<string>(1243); //錯誤
複製代碼
若是以爲對你有幫助.不妨對這一篇樸實的文章點贊關注走一波,每一個人都有本身的學習方法,高手能夠評論區留下腳印.咱們一塊兒相互交流學習~