TS入門

目錄

一、快速上手

二、vue的TS

三、使用vue-class-component

四、vue-property-decorator

五、TypeScript 不適合在 vue 業務開發中使用嗎?

六、Property 'name' has no initializer

七、下載量對比

八、tsconfig.json

九、shims-vue.d.ts

十、shims-tsx.d.ts

十一、vuex-class

參考鏈接:


 

 

 

 

 

 

一、快速上手

TypeScriptJavaScript 的強類型版本。然後在編譯期去掉類型和特有語法,生成純粹的 JavaScript 代碼。

TypeScriptJavaScript 的超集,這意味着他支持所有的 JavaScript 語法。

強類型語言的優勢在於靜態類型檢查。

TypeScript是微軟開發的語言。

vue3.0使用ts開發。

是github開源項目:https://github.com/Microsoft/TypeScript

2012 年 10 月誕生。

vscode是用ts編寫的:https://github.com/Microsoft/vscode/

裝包:

yarn global add typescript

檢查版本:

 tsc -V

初始化:

tsc --init

 

index.ts:

function greeter(person) {
  return "Hello, " + person;
}

let user = "Jane User";

document.body.innerHTML = greeter(user);

編程成js文件:

tsc index.ts

index.js:

function greeter(person) {
    return "Hello, " + person;
}
var user = "Jane User";
document.body.innerHTML = greeter(user);

類型檢查:

如果函數參數聲明是字符串,卻傳了數字,會有警告信息

function greeter(person:string) {
  return "Hello, " + person;
}

let user = 1;

document.body.innerHTML = greeter(user);

及時不傳參數也會報錯:

interface接口:

定義Person包含的字段

interface Person {
  firstName: string;
  lastName: string;
}

function greeter(person: Person) {
  return "Hello, " + person.firstName + " " + person.lastName;
}

let user = { firstName: "Jane", lastName: "User" };

document.body.innerHTML = greeter(user);

使用class創建類:

class Student {
    fullName: string;
    constructor(public firstName, public middleInitial, public lastName) {
        this.fullName = firstName + " " + middleInitial + " " + lastName;
    }
}

interface Person {
    firstName: string;
    lastName: string;
}

function greeter(person : Person) {
    return "Hello, " + person.firstName + " " + person.lastName;
}

let user = new Student("Jane", "M.", "User");

document.body.innerHTML = greeter(user);

編譯後是:

var Student = /** @class */ (function () {
    function Student(firstName, middleInitial, lastName) {
        this.firstName = firstName;
        this.middleInitial = middleInitial;
        this.lastName = lastName;
        this.fullName = firstName + " " + middleInitial + " " + lastName;
    }
    return Student;
}());
function greeter(person) {
    return "Hello, " + person.firstName + " " + person.lastName;
}
var user = new Student("Jane", "M.", "User");
document.body.innerHTML = greeter(user);

訪問網頁,index.html:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <script src="./index.js"></script>
</body>
</html>

效果:

自動補全功能:

二、vue的TS

引入Vue文件的時候需要加上.vue後綴,否則編輯器識別不到

TS路由:

import Vue from 'vue'
import VueRouter, { RouteConfig } from 'vue-router'
import Home from '../views/Home.vue'

Vue.use(VueRouter)

  const routes: Array<RouteConfig> = [
  {
    path: '/',
    name: 'Home',
    component: Home
  },
  {
    path: '/about',
    name: 'About',
    // route level code-splitting
    // this generates a separate chunk (about.[hash].js) for this route
    // which is lazy-loaded when the route is visited.
    component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
  }
]

const router = new VueRouter({
  mode: 'history',
  base: process.env.BASE_URL,
  routes
})

export default router
import Vue from 'vue'
import VueRouter, { RouteConfig } from 'vue-router'

Vue.use(VueRouter)

  const routes: Array<RouteConfig> = [
  {
    path: '/',
    redirect: '/login'
  },
  {
    path: '/login',
    component: () => import('../views/Login.vue')
  }
]

const router = new VueRouter({
  mode: 'history',
  base: process.env.BASE_URL,
  routes
})

export default router

三、使用vue-class-component

https://class-component.vuejs.org/

加加減減:

<template>
  <div>
    <div>{{count}}</div>
    <button @click="handleSub">減</button>
    <button @click="handleAdd">加</button>
  </div>
</template>

<script>
import Vue from 'vue'
import Component from 'vue-class-component'

@Component
class Login extends Vue {
  count = 0

  handleSub() {
    this.count--
  }
  
  handleAdd() {
    this.count++
  }
}

export default Login
</script>

或者:

<template>
  <div>
    <div>{{count}}</div>
    <button @click="handleSub">減</button>
    <button @click="handleAdd">加</button>
  </div>
</template>

<script>
import Vue from 'vue'
import Component from 'vue-class-component'

@Component
class Login extends Vue {
  data() {
    return {
      count: 0
    }
  }

  handleSub() {
    this.count--
  }
  
  handleAdd() {
    this.count++
  }
}

export default Login
</script>

 

v-model:

<template>
  <div>
    <input v-model="username">
  </div>
</template>

<script>
import Vue from 'vue'
import Component from 'vue-class-component'

@Component
class Login extends Vue {
  username = 'admin'
}

export default Login
</script>

掛載完聲明週期:

<template>
  <div>
    1
  </div>
</template>

<script>
import Vue from 'vue'
import Component from 'vue-class-component'

@Component
class Login extends Vue {
  mounted () {
    console.log('掛載完')
  }
}

export default Login
</script>

計算屬性:

<template>
  <div>
    {{double}}
  </div>
</template>

<script>
import Vue from 'vue'
import Component from 'vue-class-component'

@Component
class Login extends Vue {
  count = 1
  get double() {
    return this.count * 2
  }
}

export default Login
</script>

父子組件傳值:

父組件

<template>
  <div>
    <Icon :name="visible ? 'xianshimima' : 'buxianshimima'" @onClick="handleVisible"></Icon>
  </div>
</template>

<script>
import Vue from 'vue'
import Component from 'vue-class-component'
import Icon from '../components/Icon'

@Component({
  components: {
    Icon
  }
})
class Login extends Vue {
  visible = false
  
  handleVisible() {
    this.visible = !this.visible
  }
}

export default Login
</script>

子組件

<template>
  <span :class="[`icon iconfont icon-${name}`]" @click="handleClick"></span>
</template>

<script lang="ts">
import Vue from 'vue'
import { Component, Prop } from 'vue-property-decorator'

@Component
class Icon extends Vue {
  @Prop()
  name: string

  handleClick() {
    this.$emit('onClick')
  }
}

export default Icon
</script>

子組件也可以寫成這種

<template>
  <span :class="[`icon iconfont icon-${name}`]" @click="handleClick"></span>
</template>

<script lang="ts">
import Vue from 'vue'
import Component from 'vue-class-component'

const IconProps = Vue.extend({
  props: {
   name: String 
  }
})

@Component
class Icon extends IconProps {
  handleClick() {
    this.$emit('onClick')
  }
}

export default Icon
</script>

 

四、vue-property-decorator

vue屬性裝飾器

父子組件傳值,傳參

父組件:

<template>
  <div>
    <Icon :name="visible ? 'show' : 'hide'" @onClick="handleVisible"></Icon>
  </div>
</template>

<script lang="ts">
import { Vue, Component } from 'vue-property-decorator'
import Icon from '../components/Icon.vue'

@Component({
  components: {
    Icon
  }
})
class Login extends Vue {
  visible = false
  
  handleVisible(payload:object) {
    this.visible = !this.visible
  }
}

export default Login
</script>

子組件:

<template>
  <span :class="[`icon iconfont icon-${name}`]" @click="handleClick"></span>
</template>

<script lang="ts">
import { Vue, Component, Prop, Emit } from 'vue-property-decorator'

@Component
class Icon extends Vue {
  @Prop({ default: 'zhanwei' })
  name: string

  @Emit('onClick')
  handleClick() {
    return { id: 2 }
  }
}

export default Icon
</script>

五、TypeScript 不適合在 vue 業務開發中使用嗎?

https://www.zhihu.com/question/310485097/answer/591869966

 

六、Property 'name' has no initializer

Property 'name' has no initializer and is not definitely assigned in the constructor.

解決辦法一:

把tsconfig.json文件裏的strict字段改成false

解決辦法二:

在屬性名後面加歎號,這是一種修飾符,標識忽略

<template>
  <span :class="[`icon iconfont icon-${name}`]" @click="handleClick"></span>
</template>

<script lang="ts">
import { Vue, Component, Prop, Emit } from 'vue-property-decorator'

@Component
class Icon extends Vue {
  @Prop({ default: 'zhanwei' })
  name!: string

  @Emit('onClick')
  handleClick() {
    return { id: 2 }
  }
}

export default Icon
</script>

七、下載量對比

 

八、tsconfig.json

ts的配置

{
  "compilerOptions": {
    "target": "esnext", //編譯的目標版本
    "module": "esnext", //指定生成哪個模塊系統代碼
    "strict": true,  //靜態類型檢查
    "jsx": "preserve",  //
    "importHelpers": true,
    "moduleResolution": "node",
    "experimentalDecorators": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "sourceMap": true,  // 是否生成map文件
    "baseUrl": ".",
    "types": [
      "webpack-env"
    ],
    "paths": {
      "@/*": [
        "src/*"
      ]
    },
    "lib": [
      "esnext",
      "dom",
      "dom.iterable",
      "scripthost"
    ]
  },
  "include": [
    "src/**/*.ts",
    "src/**/*.tsx",
    "src/**/*.vue",
    "tests/**/*.ts",
    "tests/**/*.tsx"
  ],
  "exclude": [
    "node_modules"
  ]
}

 

九、shims-vue.d.ts

shims: 墊片

由於 TypeScript 默認並不支持 *.vue 後綴的文件,所以在 vue 項目中引入的時候需要創建一個shims-vue.d.ts 文件,放在項目應使用目錄下,例如 src/shims-vue.d.ts,用來支持*.vue 後綴的文件;

主要用於 TypeScript 識別.vue 文件,Ts默認並不支持導入 vue 文件,這個文件告訴ts 導入.vue 文件都按VueConstructor<Vue>處理

 

declare module '*.vue' {
  import Vue from 'vue'
  export default Vue
}

十、shims-tsx.d.ts

允許你以.tsx結尾的文件,在Vue項目中編寫jsx代碼

import Vue, { VNode } from 'vue'

declare global {
  namespace JSX {
    // tslint:disable no-empty-interface
    interface Element extends VNode {}
    // tslint:disable no-empty-interface
    interface ElementClass extends Vue {}
    interface IntrinsicElements {
      [elem: string]: any;
    }
  }
}

十一、vuex-class

https://www.npmjs.com/package/vuex-class

使用倉庫做加加減減

倉庫:

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

interface Payload {
  key: string,
  value: any
}

export default new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    setState(state:any, payload:Payload) {
      state[payload.key] = payload.value
    }
  },
  actions: {
  },
  modules: {
  }
})

頁面:

<template>
  <div>
    <div>{{count}}</div>
    <button @click="handleSub">減</button>
    <button @click="handleAdd">加</button>
  </div>
</template>

<script lang="ts">
import Vue from 'vue'
import Component from 'vue-class-component'
import { State, Mutation } from 'vuex-class'

@Component
class Login extends Vue {
  @State('count') count!:number
  @Mutation('setState') setState!:Function

  handleSub() {
    let count = this.count - 1
    this.setState({ key: 'count', value: count })
  }

  handleAdd() {
    let count = this.count + 1
    this.setState({ key: 'count', value: count })
  }
}

export default Login
</script>

 

十二、ts

初始化:

在空文件夾裏打開終端  -> 輸入tsc --init  自動生成tsconfig.json

{
  "compilerOptions": {
    /* Basic Options */
    // "incremental": true,                   /* Enable incremental compilation */
    "target": "es5",                          /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */
    "module": "commonjs",                     /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */
    // "lib": [],                             /* Specify library files to be included in the compilation. */
    "allowJs": true,                       /* Allow javascript files to be compiled. */
    // "checkJs": true,                       /* Report errors in .js files. */
    // "jsx": "preserve",                     /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
    // "declaration": true,                   /* Generates corresponding '.d.ts' file. */
    // "declarationMap": true,                /* Generates a sourcemap for each corresponding '.d.ts' file. */
    // "sourceMap": true,                     /* Generates corresponding '.map' file. */
    // "outFile": "./",                       /* Concatenate and emit output to single file. */
    "outDir": "./js",   //輸出文件夾                      /* Redirect output structure to the directory. */
    // "rootDir": "./",                       /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
    // "composite": true,                     /* Enable project compilation */
    // "tsBuildInfoFile": "./",               /* Specify file to store incremental compilation information */
    // "removeComments": true,                /* Do not emit comments to output. */
    // "noEmit": true,                        /* Do not emit outputs. */
    // "importHelpers": true,                 /* Import emit helpers from 'tslib'. */
    // "downlevelIteration": true,            /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
    // "isolatedModules": true,               /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */

    /* Strict Type-Checking Options */
    "strict": true,                           /* Enable all strict type-checking options. */
    // "noImplicitAny": true,                 /* Raise error on expressions and declarations with an implied 'any' type. */
    // "strictNullChecks": true,              /* Enable strict null checks. */
    // "strictFunctionTypes": true,           /* Enable strict checking of function types. */
    // "strictBindCallApply": true,           /* Enable strict 'bind', 'call', and 'apply' methods on functions. */
    // "strictPropertyInitialization": true,  /* Enable strict checking of property initialization in classes. */
    // "noImplicitThis": true,                /* Raise error on 'this' expressions with an implied 'any' type. */
    // "alwaysStrict": true,                  /* Parse in strict mode and emit "use strict" for each source file. */

    /* Additional Checks */
    // "noUnusedLocals": true,                /* Report errors on unused locals. */
    // "noUnusedParameters": true,            /* Report errors on unused parameters. */
    // "noImplicitReturns": true,             /* Report error when not all code paths in function return a value. */
    // "noFallthroughCasesInSwitch": true,    /* Report errors for fallthrough cases in switch statement. */

    /* Module Resolution Options */
    // "moduleResolution": "node",            /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
    // "baseUrl": "./",                       /* Base directory to resolve non-absolute module names. */
    // "paths": {},                           /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
    // "rootDirs": [],                        /* List of root folders whose combined content represents the structure of the project at runtime. */
    // "typeRoots": [],                       /* List of folders to include type definitions from. */
    // "types": [],                           /* Type declaration files to be included in compilation. */
    // "allowSyntheticDefaultImports": true,  /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
    "esModuleInterop": true,                  /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
    // "preserveSymlinks": true,              /* Do not resolve the real path of symlinks. */
    // "allowUmdGlobalAccess": true,          /* Allow accessing UMD globals from modules. */

    /* Source Map Options */
    // "sourceRoot": "",                      /* Specify the location where debugger should locate TypeScript files instead of source locations. */
    // "mapRoot": "",                         /* Specify the location where debugger should locate map files instead of generated locations. */
    // "inlineSourceMap": true,               /* Emit a single file with source maps instead of having a separate file. */
    // "inlineSources": true,                 /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */

    /* Experimental Options */
    "experimentalDecorators": true,   //裝飾器      /* Enables experimental support for ES7 decorators. */
    // "emitDecoratorMetadata": true,         /* Enables experimental support for emitting type metadata for decorators. */

    /* Advanced Options */
    "forceConsistentCasingInFileNames": true  /* Disallow inconsistently-cased references to the same file. */
  }
}

監視ts文件變化,自動編譯:

vscode -> 終端 -> 運行任務 -> typescript -> tsc: 監視 - (tsconfig.json的目錄)

 

課堂練習(1):

function test(name:string) {
  console.log(name)
}

test('hello3')

//元組
let tuple:[string, number, string] = ['a', 1, 'b']
console.log(tuple)

//任意值
let person:any = 'xu'
console.log(person)

//四要素:調用, 參數,返回值,作用
function fun(name:string):string {
  console.log(name)
  return name
}

fun('xu')

//never 不可到達
const error = ():never => {
  throw new Error('錯誤')
}

//error()


const loop = () => {
  while(true);
}
//loop()

console.log(1)


//枚舉
enum Color { Red = 2, Green, Blue }

console.log(Color.Red)  //2

enum obj {
  None,
  Read,
  G = '123'.length
}

console.log(obj)

enum Enum {
  A
}

let a = Enum.A
console.log(a)  //0

let na = Enum[a]
console.log(na)  //A




課堂練習(2):

function sayHello(person: string) {
  return 'Hello,' + person
}

let user:string = 'a'
console.log(sayHello(user))

let num:number = 1

//沒有顯示聲明類型,則會進行類型推斷
let a = 'a'
a = 'b'  //賦值其他類型,則會報錯

let flag:boolean = true

//數字類型的數組
let arr:number[] = [1,2]
let strArr:string[] = ['a', 'b']
let objArr:object[] = [{}]

//泛型方式
let arr1:Array<number> = [1]
let strArr1:Array<string> = ['a','b']

//元組
let arr2:[number, string, boolean] = [1, '2', true]

//null, undefined
let my_null:null = null
let my_undefined:undefined = undefined

//可以是字符串也可以是undefined
let c:string | undefined
console.log(c)

//never 從來不會出現的值
// let my_never: never = (() => {
//   throw new Error()
// })()

//any 任何類型
let my_any:any = '任何類型'
console.log(my_any)

//任何類型的數組
let arrAny:any[] = ['a', 1, true]

function run():void {
  console.log('run')
}

run()

function getName():string {
  return 'xu'
}

console.log(getName())

const myRun = ():void => {
  console.log('myRun')
}

myRun()

const myGetName = ():string => {
  return 'myGetName'
}

console.log(myGetName())

//構造函數Boolean 創造的不是布爾值
//let myBoolean:boolean = new Boolean(1)







課堂練習(3):

//函數
//沒有返回值是用void
function getInfo(name:string, age:number):string {
  return `我叫${name},今年${age}歲。`
}

console.log(getInfo('xu', 30))

let getInfo1 = (name:string, age:number):string => {
  return `我叫${name},今年${age}歲。`
}

console.log(getInfo('xu', 31))

//完整類型
let getInfo2:(name:string, age:number) => string = (name:string, age:number):string => {
  return `我叫${name},今年${age}歲。`
}

let getInfo3:Function = (name:string, age:number):string => {
  return `我叫${name},今年${age}歲。`
}

//函數可選參數,加個問好
function myInfo(name: string, age?: number):string {
  if (typeof age === 'number') {
    return `我叫${name},今年${age}歲。`
  } else {
    return `我叫${name}`
  }
}

console.log(myInfo('xu'))

//默認值
function myInfo1(name: string, age:number = 32):string {
  if (typeof age === 'number') {
    return `我叫${name},今年${age}歲。`
  } else {
    return `我加${name}`
  }
}

console.log(myInfo1('xu'))

//求和
function sum(a:number, b:number):number {
  return a + b
}

console.log(sum(1, 2))

//剩餘參數
function sum1(...rest:number[]):number {
  console.log(rest) //數組
  return rest.reduce((prev, item) => {
    return prev + item
  }, 0)
}

console.log(sum1(1, 2, 3, 4, 5))

//枚舉類型
// 0: 女, 1:男, 2:保密

enum Sex {
  gril,
  boy,
  secret
}

let xu:Sex = Sex.boy
console.log(xu)
let xu1:Sex = 3
console.log(xu1)

function getSex(sex:Sex):string {
  if (sex === Sex.gril) {
    return '我是女孩'
  } else if (sex === Sex.boy) {
    return '我是男孩'
  } else {
    return '保密'
  }
}

console.log(getSex(xu))


class A {
  v:number = 100
  test(num:number) {
    if (num > this.v) {
      console.log('大了');
    } else if (num < this.v) {
        console.log('小了')
    } else {
        console.log('對了')
    }
  }
}

let a = new A()

a.test(100)

let isDone:boolean = false

let isDone1:object = new Boolean(1)

let isDone2:Boolean = new Boolean(1)

let isDone3:boolean = Boolean(1)

//變量如果在聲明的時候,未指定其類型,那麼它會被識別爲任意值類型
let something   //let something:any
something = 1
something = 'a'

//聯合類型
let myA: string | number
myA = 'a'
myA = 1


function getLength(something: string | []):number {
  return something.length
}

let myB: string | number
myB = 'A'
myB.length
myB = 1
//myB.length  //報錯

let arr:number[] = [1, 3, 2]
arr.sort((a, b) => {
  return a - b
})


console.log(arr)

function is(ar:string,sr:string):boolean {
  let result = true
  if(ar.length===sr.length){
      for(let i=0;i<ar.length;i++){
          if(ar.indexOf(sr[i])===-1){
             result = false
          }
      }
     result = true
  } else {
    result = false
  }
  return result
}
console.log(is("asa","aas") )


function isAng(arr:string,trr:string):boolean{
  if(arr.length===trr.length){
      for(var i=0;i<arr.length;i++){
          if(arr.indexOf(trr[i])===-1){
              return false
          }
      }
      return true
  }
  return false
}

console.log(isAng('listen', 'silenta'))

課堂練習(4):


//函數重載
function add(a:string, b:string):string;
function add(a:number, b:number):number;

function add(a:any, b:any): any {
  if (typeof a === 'string') {
    return a + '---' + b
  } else {
    return a + b
  }
}

console.log(add('a', 'b'))

//類
//修飾符 pubulic protected private
//靜態屬性 static
class Person {
  public name: string
  protected age: number

  static height: number = 170

  constructor(name:string, age:number) {
    this.name = name
    this.age = age
    console.log(Person.height, Person.getHeight())
  }

  protected getName():string {
    return `我的名字叫${this.name}`
  }

  static getHeight():number {
    return this.height
  }
}

let xu = new Person('xu', 30)
//console.log(xu.getName())
console.log(Person.getHeight())

// class Animal {
//   name:string
//   constructor(name:string) {
//     this.name = name
//   }
//   sayHi() {
//     return `My name is ${this.name}`
//   }
// }

// let a = new Animal('jack')
// console.log(a.sayHi())

//繼承
class Programmer extends Person {
  job:string
  constructor(name:string, age:number, job:string) {
    super(name, age)
    this.job = job
    console.log(this.age)
  }
  getJob() {
    return `${this.getName()},年齡${this.age},我的工作是${this.job}`
  }
}

let xu1 = new Programmer('徐同保', 30, 'web前端')
//console.log(xu1.getName())
console.log(xu1.getJob())
//console.log(xu1.age)

//抽象類
abstract class Animal {
  name: string
  constructor(name: string) {
    this.name = name
  }
  getName():string {
    return this.name
  }
  abstract eat():void
}

class Cat extends Animal {
  food: string
  constructor(name: string, food: string) {
    super(name)
    this.food = food
  }
  eat():void {
    console.log(`${this.getName()}愛吃魚`)
  }
}

let ketty = new Cat('小貓', '魚')
ketty.eat()

//更簡練的寫法,不用定義name了,也不需要賦值
class MyAnimal {
  constructor(public name:string) {
  }
  getName() {
    return this.name
  }
}

let myAnimal = new MyAnimal('小貓')
console.log(myAnimal.getName())

//接口
interface Goods {
  name: string
  price: number
  flag: boolean
}

let cartList: Goods[] = [
  {
    name: '蘋果',
    price: 8,
    flag: true
  },
  {
    name: '香蕉',
    price: 5,
    flag: false
  }
]

function goodsInfo(goods:Goods) {
  console.log(`${goods.name}現在${goods.price}元一斤${goods.flag ? ',正在促銷' : ''}`)
}

cartList.forEach(item => {
  goodsInfo(item)
})

//函數接口
interface GoodsInfo {
  (goods: Goods): string
}

let myGoodsInfo: GoodsInfo = (goods:Goods):string => {
  return `${goods.name}現在${goods.price}元一斤${goods.flag ? ',正在促銷' : ''}`
}

//類接口,實現接口的時候使用implements(實現)
interface PersonI {
  name: string,
  age: number,
  getName():string
}

interface WebI {
  name: string,
  age: number,
  job: string
  getName(): string
  getJob(): string
}

//接口也可以繼承
interface WebIPlus extends PersonI {
  job: string,
  getJob(): string
}


class MyPerson implements PersonI {
  name: string
  age: number

  constructor(name:string, age:number) {
    this.name = name
    this.age = age
  }

  getName() {
    return this.name
  }
}

class Web extends MyPerson implements WebIPlus {
  job: string
  constructor(name: string, age: number, job: string) {
    super(name, age)
    this.job = job
  }

  getJob() {
    return this.job
  }

  getInfo() {
    return `${this.name},${this.age},${this.job}`
  }
}

let xu2 = new Web('xu', 30, 'web')
console.log(xu2.getInfo())





 

 

筆記:

TypeScript 中,使用 : 指定變量的類型,: 的前後有沒有空格都可以。

TypeScript 只會進行靜態檢查,如果發現有錯誤,編譯的時候就會報錯。

構造函數 Boolean 創造的對象不是布爾值。

當構造函數修飾爲 private 時,該類不允許被繼承或者實例化。

當構造函數修飾爲 protected 時,該類只允許被繼承,不允許實例化。

只讀屬性關鍵字,只允許出現在屬性聲明或索引簽名或構造函數中。

一個類只能繼承自另一個類,但是可以實現多個接口。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

參考鏈接:

一起來擁抱強大的TypeScript吧--Ts+Vue完全教程

中文手冊

英文手冊

入門教程

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章