【问题标题】:How to make typescript infer a more specific type of a class property?如何使打字稿推断出更具体的类属性类型?
【发布时间】:2018-11-02 18:19:27
【问题描述】:

我有一个类,其属性旨在由开发人员扩展,但我无法让 typescript 推断(或让开发人员能够指定)更具体的类型。在这个例子中,我的应用程序类上有一个属性“models”,它应该与“Models”类型兼容。在我的情况下,开发人员将在 100% 的时间内(几乎)用更具体的类型覆盖它,并且一旦设置就永远不会修改 - 并且将在使用之前设置。

如何帮助 typescript 理解更具体的类型 - 或允许开发人员覆盖该类型?请记住,这适用于更多属性,这使得使用“const app = new App({ config, models, stats, state });”指定类型很不方便

// External modules/types
interface Model {
  id: number;
}
interface UserModel extends Model {
  name: string;
}
interface Models {
  [service: string]: Model;
}
class Application {
  public models: Models = {};
}

// My app
const app = new Application();
app.models = {
  User: {
    id: 1,
      name: 'Kent',
  } as UserModel,
};

// app.models does not have .User

【问题讨论】:

    标签: typescript


    【解决方案1】:

    Typescript 仅在存在可以推断的泛型类型参数时才进行类型推断(您希望发生的那种)。此外,为了实现它,您通常应该有一个接受泛型参数的函数,然后可以从您传递给函数的特定类型的实际参数中推断出它的类型。

    在您的情况下,您可以使 Application 类通用,并将 models 作为参数传递给构造函数。在这种情况下,甚至没有必要为Models 提供显式接口——约束在Application 泛型类声明中内联指定:

    // External modules/types
    interface Model {
      id: number;
    }
    interface UserModel extends Model {
      name: string;
    }
    
    class Application<ServiceNames extends string, 
                  Models extends { [service in ServiceNames]: Model }> {
      constructor(models: Models) {
        this.models = models;
      }
      public models: Models;
    }
    
    // My app
    const app = new Application( {
      User: {
        id: 1,
          name: 'Kent',
      } as UserModel,
    });
    
    let n = app.models.User.name; // inferred as string
    

    【讨论】:

    • 这对我帮助很大。谢谢!
    【解决方案2】:

    使用generics:

    interface Model {
      id: number;
    }
    
    interface UserModel extends Model {
      name: string;
    }
    
    interface Models<T extends Model> {
      [service: string]: T;
    }
    
    class Application<T extends Model> {
      public models: Models<T> = {};
    }
    
    const app = new Application<UserModel>();
    
    app.models = {
      User: {
        id: 1,
        name: 'Kent',
      }
    }
    

    【讨论】:

      猜你喜欢
      • 2021-03-20
      • 2018-08-12
      • 1970-01-01
      • 1970-01-01
      • 2018-06-09
      • 1970-01-01
      • 2022-01-05
      • 1970-01-01
      • 2021-09-29
      相关资源
      最近更新 更多