有什么方法可以在打字稿中实例化普通文字类型吗?

时间:2019-10-11 08:36:49

标签: javascript typescript generics typescript-generics

我想做的事情可能是非正统的(如果说实话,边界线是无用的),所以我们开始:

我想将文字作为通用参数传递,然后实例化它。考虑以下示例:

const log = console.log;

class Root<T = {}> {
  // public y: T = {}; // this obviously doesn't work

  // again this won't work because T is used a value. Even if it worked,
  // we want to pass a literal
  // public y: T = new T();

  public x: T;
  constructor(x: T) {
    this.x = x;
  }
}

class Child extends Root<{
  name: "George",
  surname: "Typescript",
  age: 5
}> {
  constructor() {
    // Duplicate code. How can I avoid this?
    super({
      name: "George",
      surname: "Typescript",
      age: 5
    });
  }

  foo() {
    // autocomplete on x works because we gave the type as Generic parameter
    log(`${this.x.name} ${this.x.surname} ${this.x.age}`); 
  }
}


const main = () => {
  const m: Child = new Child();
  m.foo();
};
main();

这可行,但是我必须两次传递原义。一次使用通用方法进行自动补全,一次使用构造函数进行初始化。 gh。

另一种方法是在Child之外声明我的文字。像这样:

const log = console.log;

class Root<T = {}> {
  // public y: T = {}; // this obviously doesn't work

  // again this won't work because T is used a value. Even if it worked,
  // we want to pass a literal
  // public y: T = new T(); 

  public x: T;
  constructor(x: T) {
    this.x = x;
  }
}

// works but ugh..... I don't like it. I don't want to declare things outside of my class
const literal = {
  name: "George",
  surname: "Typescript",
  age: 5
}
class Child extends Root<typeof literal> {
  constructor() {
    super(literal);
  }

  foo() {
    // autocomplete on x works because we gave the type as Generic parameter
    log(`${this.x.name} ${this.x.surname} ${this.x.age}`); 
  }
}


const main = () => {
  const m: Child = new Child();
  m.foo();
};
main();

有没有一种神奇的方法可以实例化Generic类型,而无需通过构造函数再次提供它呢?

2 个答案:

答案 0 :(得分:2)

您可以使用中间包装器,该包装器既可以扩展泛型又可以调用构造函数:

function fromRoot<T>(x: T) {
  return class extends Root<T> {
    constructor() {
      super(x)
    }
  }
}

然后:

class Child extends fromRoot({
  name: "George",
  surname: "Typescript",
  age: 5
}) { etc }

PG

答案 1 :(得分:0)

您需要注意,编译后的Javascript不了解泛型,因此您不能使用它们来创建新对象。

此外,如果将Child类限制在特定对象上,我看不到这一点-为什么不定义type所期望的Child呢?然后用该类型的特定实例实例化子对象?

type MyType = {
    name: string
    surname: string
    age: number
}

class Child extends Root<MyType> {
    foo() {
        // autocomplete on x works because we gave the type as Generic parameter
        console.log(`${this.x.name} ${this.x.surname} ${this.x.age}`);
    }
}

const child = new Child({
    name: "George",
    surname: "Typescript",
    age: 5
})

如果您想重复使用该特定的Child,则可以仅导出该特定的child实例。

请参阅playground