美文网首页让前端飞
TypeScript——JavaScript文件类型检查(四)

TypeScript——JavaScript文件类型检查(四)

作者: 2o壹9 | 来源:发表于2019-12-30 09:17 被阅读0次

    导入类型

    可以使用导入类型从其它文件中导入声明。 这个语法是TypeScript特有的,与JSDoc标准不同:

    /**

    * @param p { import("./a").Pet }

    */

    function walk(p) {

        console.log(`Walking ${p.name}...`);

    }

    导入类型也可以使用在类型别名声明中:

    /**

    * @typedef Pet { import("./a").Pet }

    */

    /**

    * @type {Pet}

    */

    var myPet;

    myPet.name;

    导入类型可以用在从模块中得到一个值的类型。

    /**

    * @type {typeof import("./a").x }

    */

    var x = require("./a").x;

    @param和@returns

    @param语法和@type相同,但增加了一个参数名。 使用[]可以把参数声明为可选的:

    // Parameters may be declared in a variety of syntactic forms

    /**

    * @param {string}  p1 - A string param.

    * @param {string=} p2 - An optional param (Closure syntax)

    * @param {string} [p3] - Another optional param (JSDoc syntax).

    * @param {string} [p4="test"] - An optional param with a default value

    * @return {string} This is the result

    */

    function stringsStringStrings(p1, p2, p3, p4){

      // TODO

    }

    函数的返回值类型也是类似的:

    /**

    * @return {PromiseLike<string>}

    */

    function ps(){}

    /**

    * @returns {{ a: string, b: number }} - May use '@returns' as well as '@return'

    */

    function ab(){}

    @typedef, @callback, 和 @param

    @typedef可以用来声明复杂类型。 和@param类似的语法。

    /**

    * @typedef {Object} SpecialType - creates a new type named 'SpecialType'

    * @property {string} prop1 - a string property of SpecialType

    * @property {number} prop2 - a number property of SpecialType

    * @property {number=} prop3 - an optional number property of SpecialType

    * @prop {number} [prop4] - an optional number property of SpecialType

    * @prop {number} [prop5=42] - an optional number property of SpecialType with default

    */

    /** @type {SpecialType} */

    var specialTypeObject;

    可以在第一行上使用object或Object。

    /**

    * @typedef {object} SpecialType1 - creates a new type named 'SpecialType'

    * @property {string} prop1 - a string property of SpecialType

    * @property {number} prop2 - a number property of SpecialType

    * @property {number=} prop3 - an optional number property of SpecialType

    */

    /** @type {SpecialType1} */

    var specialTypeObject1;

    @param允许使用相似的语法。 注意,嵌套的属性名必须使用参数名做为前缀:

    /**

    * @param {Object} options - The shape is the same as SpecialType above

    * @param {string} options.prop1

    * @param {number} options.prop2

    * @param {number=} options.prop3

    * @param {number} [options.prop4]

    * @param {number} [options.prop5=42]

    */

    function special(options) {

      return (options.prop4 || 1001) + options.prop5;

    }

    @callback与@typedef相似,但它指定函数类型而不是对象类型:

    /**

    * @callback Predicate

    * @param {string} data

    * @param {number} [index]

    * @returns {boolean}

    */

    /** @type {Predicate} */

    const ok = s => !(s.length % 2);

    当然,所有这些类型都可以使用TypeScript的语法@typedef在一行上声明:

    /** @typedef {{ prop1: string, prop2: string, prop3?: number }} SpecialType */

    /** @typedef {(data: string, index?: number) => boolean} Predicate */

    @template

    使用@template声明泛型:

    /**

    * @template T

    * @param {T} p1 - A generic parameter that flows through to the return type

    * @return {T}

    */

    function id(x){ return x }

    用逗号或多个标记来声明多个类型参数:

    /**

    * @template T,U,V

    * @template W,X

    */

    还可以在参数名前指定类型约束。 只有列表的第一项类型参数会被约束:

    /**

    * @template {string} K - K must be a string or string literal

    * @template {{ serious(): string }} Seriousalizable - must have a serious method

    * @param {K} key

    * @param {Seriousalizable} object

    */

    function seriousalize(key, object) {

      // ????

    }

    @constructor

    编译器通过this属性的赋值来推断构造函数,但你可以让检查更严格提示更友好,你可以添加一个@constructor标记:

    /**

    * @constructor

    * @param {number} data

    */

    function C(data) {

      this.size = 0;

      this.initialize(data); // Should error, initializer expects a string

    }

    /**

    * @param {string} s

    */

    C.prototype.initialize = function (s) {

      this.size = s.length

    }

    var c = new C(0);

    var result = C(1); // C should only be called with new

    通过@constructor,this将在构造函数C里被检查,因此你在initialize方法里得到一个提示,如果你传入一个数字你还将得到一个错误提示。如果你直接调用C而不是构造它,也会得到一个错误。

    不幸的是,这意味着那些既能构造也能直接调用的构造函数不能使用@constructor。

    @this

    编译器通常可以通过上下文来推断出this的类型。但你可以使用@this来明确指定它的类型:

    /**

    * @this {HTMLElement}

    * @param {*} e

    */

    function callbackForLater(e) {

        this.clientHeight = parseInt(e) // should be fine!

    }

    @extends

    当JavaScript类继承了一个基类,无处指定类型参数的类型。而@extends标记提供了这样一种方式:

    /**

    * @template T

    * @extends {Set<T>}

    */

    class SortableSet extends Set {

      // ...

    }

    注意@extends只作用于类。当前,无法实现构造函数继承类的情况。

    @enum

    @enum标记允许你创建一个对象字面量,它的成员都有确定的类型。不同于JavaScript里大多数的对象字面量,它不允许添加额外成员。

    /** @enum {number} */

    const JSDocState = {

      BeginningOfLine: 0,

      SawAsterisk: 1,

      SavingComments: 2,

    }

    注意@enum与TypeScript的@enum大不相同,它更加简单。然而,不同于TypeScript的枚举,@enum可以是任何类型:

    /** @enum {function(number): number} */

    const Math = {

      add1: n => n + 1,

      id: n => -n,

      sub1: n => n - 1,

    }

    相关文章

      网友评论

        本文标题:TypeScript——JavaScript文件类型检查(四)

        本文链接:https://www.haomeiwen.com/subject/exepoctx.html