如何将通用类型转换为Typescript中Record和接口的联合类型?

huangapple go评论73阅读模式
英文:

How to make a generic type an union type of Record<K,V> and an interface in Typescript?

问题

I want to declare a couple singleton class (Angular service) that must have some members named after an enum. Until now I had it as a const:

enum RewardId {
  HEHE = 'AdMobRewardIdHEHE',
  HOHO = 'AdMobRewardIdHOHO',
}

interface RewardObject {
  id: RewardId;
  someData: any
}

const MyConst: Record<RewardId, RewardObject> = {
  [RewardId.HEHE]: {
    id: RewardId.HEHE,
    someData: 'someData'
  },

  [RewardId.HOHO]: {
    id: RewardId.HOHO,
    someData: 'someData'
  }
}

If I add a new RewardId Typescript lets me know that I have to implement it on MyConst this is what I want

如何将通用类型转换为Typescript中Record<K, V>和接口的联合类型?
[Typescript Playground link][2]

Now, I want to change it to a service (so a class) because it is easier to test and I also need some methods there.

interface VaultMethods {
  someMethod1(): void;
  someMethod2(): void;
}

class MyClass implements Record<RewardId, RewardObject>, VaultMethods {
  [RewardId.HEHE] = {
    id: RewardId.HEHE,
    someData: 'someData'
  };

  [RewardId.HOHO] = {
    id: RewardId.HOHO,
    someData: 'someData'
  };

  someMethod1() { }

  someMethod2() { }
}

[Typescript Playground][3]

As the final step, I need this to convert that class definition into a generic interface:

This does not work interface Vault<K, V> extends VaultMethods, Record<K, V> because An interface can only extend an object type or intersection of object types with statically known members.

If I make it a type it kind of works in the way that TypeScript asks me to implement the methods and members

type Vault<K, V> = Record<K, V> & VaultMethods;
class MyClass2 implements Vault<RewardId, RewardObject> {
  
}

Typescript Playground
如何将通用类型转换为Typescript中Record<K, V>和接口的联合类型?

But It shows an error in the Type Definition:
如何将通用类型转换为Typescript中Record<K, V>和接口的联合类型?

Is there a way to fix this?

英文:

I want to declare a couple singleton class (Angular service) that must have some members named after an enum. Until now I had it as a const:

enum RewardId {
  HEHE = &#39;AdMobRewardIdHEHE&#39;,
  HOHO = &#39;AdMobRewardIdHOHO&#39;,
}

interface RewardObject {
  id: RewardId;
  someData: any
}


const MyConst: Record&lt;RewardId, RewardObject&gt; = {
  [RewardId.HEHE]: {
    id: RewardId.HEHE,
    someData: &#39;someData&#39;
  },

  [RewardId.HOHO]: {
    id: RewardId.HOHO,
    someData: &#39;someData&#39;
  }
}

If I add a new RewardId Typescript lets me know that I have to implement it on MyConst this is what I want

如何将通用类型转换为Typescript中Record<K, V>和接口的联合类型?
[Typescript Playground link][2]

Now, I want to change it to a service (so a class) because it is easier to test and I also need some methods there.

interface VaultMethods {
   someMethod1(): void;
  someMethod2(): void;
}

class MyClass implements Record&lt;RewardId, RewardObject&gt;, VaultMethods {
  [RewardId.HEHE] = {
    id: RewardId.HEHE,
    someData: &#39;someData&#39;
  };

  [RewardId.HOHO] = {
    id: RewardId.HOHO,
    someData: &#39;someData&#39;
  };

  someMethod1() { }

  someMethod2() { }
}

[Typescript Playground][3]

As final step I need this to convert that class definition in a generic interface:

This does not work interface Vault&lt;K, V&gt; extends VaultMethods, Record&lt;K, V&gt; because An interface can only extend an object type or intersection of object types with statically known members.

If I make it a type it kind of works in the way that Typescript ask me to implement the methods and members

type Vault&lt;K, V&gt; = Record&lt;K, V&gt; &amp; VaultMethods;
class MyClass2 implements Vault&lt;RewardId, RewardObject&gt; {
  
}

Typescript Playground
如何将通用类型转换为Typescript中Record<K, V>和接口的联合类型?

But It shows an error in the Type Definition:
如何将通用类型转换为Typescript中Record<K, V>和接口的联合类型?

Is there a way to fix this?

答案1

得分: 4

It seems that you were missing a constraint on type parameter K. Since you're passing it to Record and that the K is probably an enum, you can say that K extends string.

type Vault<K extends string, V> = Record<K, V> & VaultMethods;

[typescript playground](https://www.typescriptlang.org/play/?ssl=17&ssc=28&pln=17&pc=13#code/KYOwrgtgBASsDuBDATgEwJKqgbwLACgooAJAUTKgF4oByAQVQFkB7AIziTUzLJoBoCRYgHkRVWgxbsEKDKhEj%20gqAHoVxOhvH0mbDrO6a6S-AF8CBAJYgALsGQAzRAGNgsGWmGsAVsGc2cZUtUAC53TjkAbmUAZ2YIYAARRBtEMMQQAE8Cc3wrW3snVygANUQwABsbRmAbAAtmVBjAwiI4hJr6xoBGAAoASjCAN2Zg6Nb24E6G1AAmAeHR1HHcghtMgAc3MsqbAB4AaShgAA87ECaoGJtkawBzPlKAPnE4Z2Y0Q8eSl4AyUvKVWmjRi4wIzgqiBizUYmQAwpDoVBLBANhVgAlbM0dlU9vouKhHvjUF5fP4XnhWgBtYmYAB0PFIAF1xJSiERgmFaagGeRSAJWm14kkUmlaJNkqkaMpTGDqdyGaJhCzqGz2ZzwgYeQphAL2VdhZKxTQJaLpa1ZRYJsLgag%20v0cFBVtaOrUZvMHdgnTkCEA


<details>
<summary>英文:</summary>

It seems that you were missing a constraint on type parameter `K`. Since you&#39;re passing it to `Record` and that the K is probably an enum, you can say that `K` extends `string`.

type Vault<K extends string, V> = Record<K, V> & VaultMethods;

[typescript playground][1]


  [1]: https://www.typescriptlang.org/play/?ssl=17&amp;ssc=28&amp;pln=17&amp;pc=13#code/KYOwrgtgBASsDuBDATgEwJKqgbwLACgooAJAUTKgF4oByAQVQFkB7AIziTUzLJoBoCRYgHkRVWgxbsEKDKhEj%20gqAHoVxOhvH0mbDrO6a6S-AF8CBAJYgALsGQAzRAGNgsGWmGsAVsGc2cZUtUAC53TjkAbmUAZ2YIYAARRBtEMMQQAE8Cc3wrW3snVygANUQwABsbRmAbAAtmVBjAwiI4hJr6xoBGAAoASjCAN2Zg6Nb24E6G1AAmAeHR1HHcghtMgAc3MsqbAB4AaShgAA87ECaoGJtkawBzPlKAPnE4Z2Y0Q8eSl4AyUvKVWmjRi4wIzgqiBizUYmQAwpDoVBLBANhVgAlbM0dlU9vouKhHvjUF5fP4XnhWgBtYmYAB0PFIAF1xJSiERgmFaagGeRSAJWm14kkUmlaJNkqkaMpTGDqdyGaJhCzqGz2ZzwgYeQphAL2VdhZKxTQJaLpa1ZRYJsLgag%20v0cFBVtaOrUZvMHdgnTkCEA

</details>



huangapple
  • 本文由 发表于 2020年1月6日 16:16:01
  • 转载请务必保留本文链接:https://go.coder-hub.com/59608718.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定