代码之家  ›  专栏  ›  技术社区  ›  HelloEdit

typescript自定义属性名称

  •  1
  • HelloEdit  · 技术社区  · 6 年前

    我目前面临以下情况:

    我编写了js模块的typescript定义,该模块的调用函数如下:

    declare function module<I>(
      instance: I,
      options: module.Options
    ): module.Module<I>
    

    以及模块命名空间:

    declare namespace module {
      interface Module<I> {
        use(): any;
        after(): any;
        ready(): any;
      }
    
      interface Options {
        expose?: {
          use?: string;
          after?: string;
          ready?: string;
        }
      }
    }
    

    expose选项用于更改module.module中的方法名,但我不知道:

    1)就像在使用时有一个默认回退,after和ready名称

    2)让用户为这些方法指定一个新名称

    我不知道typescript是否有这种灵活性^^

    1 回复  |  直到 6 年前
        1
  •  1
  •   artem    6 年前

    是的,它有一定的灵活性,但不太灵活-您可以使用从数据推断出的方法名的类型,但数据必须以字符串文本的形式出现-您不能使用包含方法所需名称的变量,请将该变量传递给 module 函数并神奇地获取具有该名称的类型。

    我不确定这是否值得:

    declare function module<I, U extends string = string, A extends string = string, R extends string = string>(
      instance: I,
      options: module.Options<U, A, R>
    ): module.Module<I, U, A, R>
    
    declare namespace module {
    
      interface DefaultModule<I> {
        use(): any;
        after(): any;
        ready(): any;
        }
    
        type Module<I, U extends string, A extends string, R extends string> =
            string extends U ? DefaultModule<I> :
            string extends A ? DefaultModule<I> :
            string extends R ? DefaultModule<I> :
            // here we have specific names in U, A, R, not just strings
            { [u in U]: () => any } & { [a in A]: () => any } & { [r in U]: () => any }
            ;    
    
      interface Options<U extends string = string, A extends string = string, R extends string = string> {
        expose?: {
          use?: U;
          after?: A;
          ready?: R;
        }
      }
    }
    
    interface ExposeNames<U extends string, A extends string, R extends string> {
        useName: U;
        afterName: A;
        readyName: R;
    }
    
    function moduleOptions<U extends string, A extends string, R extends string>({useName, afterName, readyName}: ExposeNames<U, A, R>): module.Options<U, A, R> {
        return {
            expose: {use: useName, after: afterName, ready: readyName}
        }
    }
    
    const moduleA = module({}, {});
    moduleA.use();
    
    const moduleB = module({}, moduleOptions({ useName: 'use1', afterName: 'after1', readyName: 'ready1' }));
    moduleB.use1();