精华内容
下载资源
问答
  • new List() const elem = list.remove(0) const boolean = list.remove({} as Elem) 虽然重载可以解决这个问题,但是按着问题描述 elem 是一个 any 类型,那么就意味着它可以是一个数字,那么当它是数字时是应该走...

    type Elem = {}

    class List {

    elems: Elem[] = []

    remove(index: number): Elem

    remove(elem: Elem): boolean

    remove(indexOrElem: number | Elem): Elem | boolean {

    // TODO 该函数有歧义(当参数与数组元素均为number类型时,是按照index还是ele方式来处理),暂定先按index来处理

    if (typeof indexOrElem === 'number') {

    const [ deletedEle ] = this.splice(indexOrElem, 1)

    return deletedEle

    } else {

    const index = this.indexOf(indexOrElem)

    if (index === -1) {

    return false

    } else {

    this.remove(index)

    return true

    }

    }

    }

    splice(index: number, deleteCount: number): Elem[] {

    return this.elems

    }

    indexOf(ele: Elem): number {

    return 0

    }

    }

    const list = new List()

    const elem = list.remove(0)

    const boolean = list.remove({} as Elem)

    虽然重载可以解决这个问题,但是按着问题描述 elem 是一个 any 类型,那么就意味着它可以是一个数字,那么当它是数字时是应该走索引的逻辑还是元素的逻辑呢?这样这个 API 就很保证稳定的工作,所以个人不太建议设计这样的 API。

    可以考虑将 API 拆细一些,保证功能的单一。

    remove(elem: Elem) {

    const index = this.indexOf(elem)

    if (index === -1) {

    return false

    } else {

    this.remove(index)

    return true

    }

    }

    removeByIndex(index: number) {

    const [ deletedEle ] = this.splice(index, 1)

    return deletedEle

    }

    展开全文
  • // 抽象类和重写重载继承多态 export {} // 抽象类.抽象方法不包括具体实现, 必须在子类里面实现; 抽象方法必须写在抽象类里面 abstract class Animal { //抽象类 name: string abstract speak():void //抽象...
    // 抽象类和重写重载继承多态
    
    export {}
    
    // 抽象类.抽象方法不包括具体实现, 必须在子类里面实现; 抽象方法必须写在抽象类里面
    abstract class Animal {  //抽象类
      name: string
      abstract speak():void  //抽象方法
    }
    
    class Cat extends Animal {
      speak(): void {             //重写父类的方法speak
        console.log('喵喵喵');
      }
    }
    
    
    
    //重写: 子类重写继承自父类的方法
    //重载: 函数的重载
    function double(val:string)
    function double(val:number)
    function double(val:any){
      if(typeof val === 'number') {
        return val*2
      } else if(typeof val === "string") {
        return val + val
      }
    }
    double(2)
    double('1')
    // double(true)  //加上上面两句之后这里如果传布尔值就会报错, 也即函数的重载
    
    
    
    // 继承和多态
    // 继承: 主要是通过extends
    // 多态: 同一个方法,不同的子类有不同的实现, 如父类的speak方法,子类Cat的实现如上, 而其他子类的实现如下:
    
    class Dog extends Animal {
      speak(): void {             //重写父类的方法speak
        console.log('汪汪汪');
      }
    }
    
    展开全文
  • 一。函数的定义 二。参数(可选参数/默认参数/剩余参数) //函数的参数 function add(x : number,y : number) : number{ return x + y } //可选参数? function show(name,age?...方法的重载

    一。函数的定义

    二。参数(可选参数/默认参数/剩余参数)

    //函数的参数

    function add(x : number,y : number) : number{

      return x + y

    }

    //可选参数?

    function show(name,age? : number) : void{

      console.log(name,age)

    }

    show('zs')

     

    //默认参数

    注意:可选参数,一般都要放在参数列表的最后面

    function show1(name,age : number = 20) : void{

      console.log(name,age)

    }

     

    show('zs',10)  //传了参数,用传的参,没有传参,采用默认参数

     

    //剩余参数

    //剩余参数(不确定有多少个参数)

    function add1(x1,x2,...x : number[]) : number{

      let sum = 0

      for(let i = 0;i<x.length;i++){

        sum += x[i]

      }

      return x1 + x2 + sum

    }

     

    let sum = add1(1,2,3,4,5,6,7,8)

    console.log(sum)

     

     

     

    三。方法的重载

     

    展开全文
  • 自动加载与热重载:模块代理 上面已经对热重载的实现原理进行了基本的介绍,下面将结合更实际和简洁的方式,来实现一个完整的自动加载和热重载模块的方案:模块代理。结合全局命名空间,该方案能够利用声明合并来在...

    427cc5ad625b42bb5382c8c6fae70fcc.png

    很多时候,特别是在开发过程中,我们希望能够不需要频繁重启服务就立即应用改动的代码。但在常驻内存的服务器应用中,要实现这种需求并不简单。

    强引用和弱引用

    因为常驻内存的自然特性,变量存在强引用的问题,特别是在像 CommonJS 这样的模块加载方案中,一旦 `require/import` 的模块被赋值到了新的变量中,它就自动形成了对模块的“拷贝”,即原模块发生改变之后,在导入的地方,这个改变将毫无作用。例如下面的例子:

    // app.ts
    const app = { name: "app" /* ... */ };
    export default app;
    
    
    // index.ts
    import app from "./app";
    
    console.log(app.name); // => app
    

    现在,修改 app.ts 中的代码为如下这样子:

    const app = { name: "my-app" /* ... */ };
    export default app;
    

    这并没有任何作用,因为如果不重启进程,新代码将不会被运行。但 NodeJS 提供了重载模块的方案。默认地,NodeJS 将模块缓存到 `require.cache` 中,因此,理论上,只要删除缓存,并重新导入即可。因此,开发者可以实现下面这样的逻辑,用来监听文件改变,并自动重载模块。

    import { watch } from "chokidar"; // chokidar 是一个兼容更多平台的文件监听模块
    
    watch(__dirname).on("change", (filename) => {
        delete require.cache[filename];
        require(filename);
    });
    

    但实际上这毫无作用,因为在 index.ts 中,`import app from "./app";` 创建了一个对模块的
    强引用(不完整的拷贝),当模块本身发生了改变并重载(重新赋值到缓存中),强引用就会立即变成完整的拷贝,就像下面这样:

    var cache = { name: "app" };
    var copy = cache;
    
    // 如果 cahce 被重载
    cache = { name: "my-app" };
    
    // copy 将不会有任何改变
    console.log(capy.name) // => app
    

    要实现缓存重载后原来的引用也能够发生改变,则需要通过"弱引用"导入。即每一处使用导入对象的地方,都重新检查缓存,例如重新调用 `require`,类似下面这样:

    console.log(require("./app").default.name);
    

    如此一来,当缓存被重载,`require` 就会返回新的对象。

    自动加载与热重载:模块代理

    上面已经对热重载的实现原理进行了基本的介绍,下面将结合更实际和简洁的方式,来实现一个完整的自动加载和热重载模块的方案:模块代理。结合全局命名空间,该方案能够利用声明合并来在 TypeScript 中享受到诸如类型提示和类型检查的优势。
    首先,利用声明合并来定义所需的全局接口类型,使它们能够在项目的任何地方都可以直接使用。

    declare global {
        interface ModuleConstructor<T> {
            new (...args: any[]) => T;
            /** 用于获取模块单例 */
            getInstance?(): T;
        }
    
        interface ModuleProxy<T, R1 = any, R2 = any, R3 = any, R4 = any, R5 = any> {
            /** 模块的名称(包快命名空间) */
            readonly name: string;
            /** 模块的路径(不包含后缀名) */
            readonly path: string;
            /** 模块的构造函数(仅支持默认导出类) */
            readonly ctor: ModuleConstructor<T>;
    
            /** 创建模块的实例(相当于 new this.ctor()) */
            create(): T;
            create(arg1: R1): T;
            create(arg1: R1, arg2: R2): T;
            create(arg1: R1, arg2: R2, arg3: R3): T;
            create(arg1: R1, arg2: R2, arg3: R3, arg4: R4): T;
            create(arg1: R1, arg2: R2, arg3: R3, arg4: R4, arg5: R5): T;
            create(...args: any[]): T;
    
            /** 设置/获取模块的 singleton 实例(单例) */
            instance(ins?: T): T;
        }
    }
    

    接下来,需要实现真正的 ModuleProxy 构造器,并且它支持通过“点语法”来无限延展,从而形成命名空间,来实现自动加载模块(就像在其他语言如 PHP 或者 Java 中那样)。

    import { nrmalize } from "path";
    
    export class ModuleProxy {
        private root: { name: string, path: string };
        private children: { [name: string]: ModuleProxy } = {};
    
        constructor(
            readonly name: string,
            path: string,
            private singletons: { [name: string]: any } = {},
        ) {
            this.root = {
                name: name.split(".")[0],
                path: normalize(path)
            };
        }
    }
    

    为了支持点语法自动延展命名空间,我这里使用 js-magic 包并实现 `__get``__has` 魔术方法,从而在访问不存在的属性时,能够自动生成新的模块代理实例。

    import { applyMagic } from "js-magic";
    
    @applyMagic
    export class ModuleProxy {
        // ...
        protected __get(prop: string) {
            if (prop in this) {
                return this[prop];
            } else if (prop in this.children) {
                return this.children[prop];
            } else if (typeof prop != "symbol") {
                // 当访问不存在的实例时,创建并返回新的 ModuleProxy 实例
                return (this.children[prop] = new ModuleProxy(
                    (this.name && `${this.name}.`) + String(prop), // 扩展名称
                    this.root.path,
                    this.singletons,
                ));
            }
        }
    
        protected __has(prop: string) {
            return (prop in this) || (prop in this.children);
        }
    }
    

    接下来,利用 Getter 来实现访问模块构造函数,其方案是优先访问缓存,当缓存不存在时,通过调用 `require` 函数来动态导入模块,从而实现模块代理的自动加载机制。

    import { resolve } from "path";
    
    export class ModuleProxy {
        // ...
        get path(): string {
            // 计算模块的路径
            return resolve(this.root.path, ...this.name.split(".").slice(1));
        }
    
        get ctor(): ModuleConstructor<any> {
            let { path } = this;
            // 同时检查 js 和 ts 模块,以兼容 node 和 ts-node 环境
            let mod = require.cache[path + ".ts"] || require.cache[path + ".js"];
    
            if (!mod) { // 如果缓存不存在,则导入
                mod = require(path);
    
                // 仅支持默认导出,并且必须是一个类 (函数)
                if (!mod.default || typeof mod.default !== "function") {
                    throw new TypeError(`Module ${this.name} is not a constructor.`);
                }
            } else {
                mod = mod.exports;
            }
    
            return mod.default;
        }
    }
    

    然后实现 `create()``instance()` 方法,不过它们是额外的支持,如果不需要,则完全可以忽略它们(需要同时删除全局 ModuleProxy<T> 接口中的方法)。

    export class ModuleProxy {
        // ...
        create(...args: any[]) {
            return new this.ctor(...args);
        }
    
        instance(ins?: any) {
            if (ins) {
                return (this.singletons[this.name] = ins);
            } else if (this.singletons[this.name]) {
                return this.singletons[this.name];
            } else {
                let ins: any;
    
                // 使用多种方式尝试获取单例
                if (typeof this.ctor.getInstance === "function") {
                    ins = this.ctor.getInstance();
                } else {
                    try {
                        ins = this.create();
                    } catch (err) {
                        ins = Object.create(this.ctor.prototype);
                    }
                }
    
                return (this.singletons[this.name] = ins);
            }
        }
    }
    

    最后需要实现的是文件监听和热重载功能,即在检测到文件发生改变的时候,能够立即删除模块的缓存,从而在下一次访问 `ctor` 属性的时候重新导入模块。

    export class ModuleProxy {
        // ...
        // 提供可选的 listener 回调函数以便能够自定义
        watch(listener?: (event: "change" | "unlink", filename: string) => void) {
            let { path } = this.root;
            let clearCache = (event: string, filename: string, cb: Function) => {
                let name = this.resolve(filename);
    
                if (name) {
                    delete this.singletons[name]; // 删除单例缓存
                    delete require.cache[filename]; // 删除模块缓存
                    cb && cb(event, filename);
                }
            };
    
            // 同时监听文件改变和删除事件
            return watch(path, {
                awaitWriteFinish: true,
                followSymlinks: false
            }).on("change", (filename) => {
                clearCache("change", filename, listener);
            }).on("unlink", (filename) => {
                clearCache("unlink", filename, listener);
            }).on("unlinkDir", dirname => {
                dirname = dirname + sep;
    
                for (let filename in require.cache) {
                    if (startsWith(filename, dirname)) {
                        clearCache("unlink", filename, listener);
                    }
                }
            });
        }
    }
    

    创建根实例

    要使用这个模块代理功能,首先需要创建一个根实例,并将其赋值到 global 对象上,这样在项目的任何地方都可以使用这个根实例,来通过点语法(命名空间)代理访问模块。

    const app = global["app"] = new ModuleProxy("app", __dirname);
    
    // 开启文件监听和热重载
    app.watch();
    

    为了在 TypeScript 中使用,还需要通过声明合并将 `app` 作为一个命名空间合并到 global 命名空间下。

    declare global {
        namespace app { }
    }
    

    创建模块与命名空间

    然后,就可以创建任何需要自动加载和热重载的模块,模块的路径和命名空间一一对应,为了在 TypeScript 中使用类型提示和类型检查,同样的,需要将其合并到全局命名空间,并且文件必须将模块类做为默认导出。

    // bootstrap.ts
    declare global {
        namespace app {
            const bootstrap: ModuleProxy<Bootstrap>
        }
    }
    
    export default class Boostrap {
        init() {
            // ...
        }
    }
    

    如果一个模块在文件夹中,则需要将文件夹名称作为一个新的命名空间:

    // services/user.ts
    declare global {
        namespace app {
            namespace services {
                const user: ModuleProxy<User, string>;
            }
        }
    }
    
    export default class User {
        constructor(protected name: string) { }
    
        getName() {
            return this.name;
        }
    }
    

    然后在项目的任何地方,就可以直接通过命名空间来访问模块了,并享受到热重载带来的好处。

    app.bootstrap.instance().init();
    
    var user = app.services.user.create("Mr. World");
    console.log(user.getName()); // => Mr. World
    

    注意事项

    利用命名空间,模块代理能够进行动态加载和热重载,但任何时候都需要注意,不要将命名空间返回的模块构造函数赋值给最外层作用域的变量,因为如果上下文模块不支持热重载的话,它又会回到强引用的陷阱当中。

    最终实现

    Alar 是一个实现了上述逻辑的简单框架,并在其基础上添加了模块代理的远程服务 (IPC/RPC) 支持,如果需要了解更多细节,可以在 GitHub 上查看它,或者直接查看我的下一篇介绍该框架的文章《使用 Alar 框架轻松实现热重载和分布式 NodeJS 应用》。

    hyurl/alargithub.com
    7d0c23a870d0067d27225dcf092ba44e.png
    Ayonium:使用 Alar 框架轻松实现热重载和分布式 NodeJS 应用zhuanlan.zhihu.com
    5818cc8a82f2227d4f5516a47166f764.png
    展开全文
  • <div><p>该提问来源于开源项目:Tencent/puerts</p></div>
  • 重载 TypeScript 允许我们定义多个函数类型定义来进行函数重载,编译器会根据定义列表去处理函数的调用。 function foo(x: number): string function foo(x: string): string function foo(x): any { if (typeof x ...
  • ts

    2020-09-18 18:36:02
    // 重载 // function cz(name: string): any // function cz(name: string, age?: number): any { // if (age) { // return `我叫${name}今年${age}岁`; // } else { // return `我叫${name}`; // } // } // // ...
  • * 5)函数重载 * 1.先声明 * 2.用any写实现(加很多判断) */ function test6(n: string): void; function test6(n: number): number; function test6(c: any): void | number { if(typeof c == "number"){ }...
  • TS笔记

    2021-02-01 11:27:46
    TS笔记基础介绍作用编译运行ts数据类型函数TS类todoList ...8. 提供一些语法糖,方便实践面向对象的编程(类,接口,枚举,泛型,方法重载) 编译运行 npm install -g typescript 手动:tsc *.js 自动:配合vscod
  • tsts学习笔记

    2020-06-14 17:17:37
    一、函数重载 // 函数重载 function add(...rest: number[]):number; function add(...rest: string[]):string; function add(...rest: any):any { let first = rest[0]; if(typeof first === 'number') { return...
  • java之重载和重写

    2020-08-12 18:00:33
    方法重载: 方法重载是指方法名和方法的返回类型都相同,但方法参数不一样. 参数不一样体现在参数个数、参数类型以及参数类型的顺序 不一样(三条满足一条即不一样). 举个例子: Test.java public class Test { public...
  •  1、读取一个TS包,注意Packet重载了>>操作符  2、如果TS包的PID等于0,表示TS包中装的是PAT  (1)从TS包中把PAT读取出来,PAT也重载了>>操作符  (2)把PAT中的program读取出来  (3)遍历所有的program  
  • Scala重载解析

    2015-06-01 17:11:54
    如果一个标识符或选择e引用了数个类的成员,则将使用引用的上下文来推断唯一的成员。使用的方法将依赖于e是否被用作一个函数。...否则,设Ts是通过用未定义类型来类型化每个参量所得到的类型向量。首先要...
  • TypeScript基础入门 - 函数 - 重载

    千次阅读 2018-08-21 22:28:17
    TypeScript基础入门 - 函数 - 重载 项目实践仓库 https://github.com/durban89/typescript_demo.git tag: 1.2.5 为了保证后面的学习演示需要安装下ts-node,这样后面的每个操作都能直接运行看到输出的结果。 ...
  • 方法装饰器不能用在声明文件( .d.ts),重载或者任何外部上下文(比如declare的类)中。 方法装饰器表达式会在运行时当作函数被调用,传入下列3个参数: 对于静态成员来说是类的构造函数,对于实例成...
  • ts装饰器

    2020-11-17 20:13:13
    类装饰器重载 返回一个继承与Fal类的类,并且里面的属性与方法要一致。 属性装饰器 对于实例成员。target是类的原型对象 对于静态成员,target是类的构造函数 方法装饰器 对实例成员来说,target是类的...
  • Ts_05类的标注

    2021-04-20 15:39:57
    文章目录Ts面向对象编程思想类类的概念类的基础class构造函数成员属性与方法定义this关键字构造函数参数属性继承super关键字方法的重写与重载方法的重写(函数的参数个数和类型是一样的,但是逻辑不一样就是方法的...
  • ts typescript.txt

    2020-03-13 21:09:23
    04 Typescript中的函数 函数的定义 可选参数 默认参数 剩余参数 函数重载 箭头函数 (31分50秒).rar 05 Typescript中的类 Es5中的类和静态方法 继承 (原型链继承、对象冒充继承、原型链+对象冒充组合继承...
  • using System;using System.Collections.Generic;using System.Linq;using System.Text; namespace ConsoleApplication7{ class Test { static void Main(string[] args) { Test ts...
  • 一定要学会看英文! 命令行报错→有道词典→复制到谷歌 ...ts 主要就是为了解决 js 的一些错误,... 函数重载:可以支持多种形式的参数类型 安装 sudo apt-get install nodejs (查看版本:node -v) sudo ...
  • java重载与重写的区别

    2014-04-03 16:30:09
    方法重载: 方法重载是指方法名和方法的返回类型都相同,但方法参数不一样. 参数不一样体现在参数个数和参数类型不一样. 举个例子: Test.java ...Test ts = new Test() ; System.out.printl
  • 1.函数的重载 function getInfo(name: string):string; function getInfo(name: string, age: number):string; // 不符合上面两种格式会报错 function getInfo(name: any, age?: any):any { /* code... */ } 2....
  • 回顾C#中重载的概念:1.方法重载是指在同一个类中方法同名,参数不同,调用时根据实参的形式,选择与他匹配的方法执行操作的一种...在JS中本身不支持重载的,而在TS中使用可以"变通"的支持重载:1.先申明...
  • 我们来看一下C ++中的一个新模式,重载模式,以及如何在代码中实现它。 访问std::variant的模式: template&lt;class... Ts&gt; struct overload : Ts... { using Ts::operator()...; }; template&lt;...
  • 方法重载:方法重载是指方法名和方法的返回类型都相同,但方法参数不一样.参数不一样体现在参数个数和参数类型不一样.举个例子: Test.java-------------- public class Test{  public static void main(String[] args...
  • typescript(三)--ts中函数

    千次阅读 2018-07-21 14:03:33
    如题。 ts中函数语法大致和es6一致,因为ts中也兼容es5的语法,故es5的代码在ts中也并不会报错。又因为ts比js多了可选的类型,故ts的语法看起来更... 函数重载  箭头函数 es6 ================================...
  • 代码: // 本节内容 // 1.函数的定义 // 2.参数(可选参数/默认参数/剩余参数) // 3.方法的重载 // js // function add(x,y){ // return x+y // } ...// ts // 1.函数的定义 fu...
  • 然后,设置快速重载: ./dev.sh 或者,运行: npm run ts-watch和npm run dev 在单独的终端中。 项目的TypeScript将进行增量编译,并且更改时会将静态文件复制到dist /文件夹中。 更改任何静态文件或...

空空如也

空空如也

1 2 3 4 5
收藏数 87
精华内容 34
关键字:

ts重载