最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

typescript - How do I write a generic that takes an interface where the keys are anything but the values are forced to be keys?

programmeradmin2浏览0评论

Let's say I want to make a function called doThing that takes a generic. When using this function, I intend to manually input the generic with an interface which could have any keys, but the values should always be strings. I would like TypeScript to give me an error if any of the interface's values are not strings, like this:

function doThing<T extends ???> {
  // do a thing
}

interface GoodInterface {
  foo: string
  bar?: string
}

interface BadInterface {
  foo: number
  bar: string
}

doThing<GoodInterface>() // should work
doThing<BadInterface>() // should give a type error

Note that in GoodInterface, the optional bar key with string value is still accepted.

What would the generic have to extend to achieve this behavior? My initial thought was to extend Record<string, string>, but that gave me the error Index signature for type 'string' is missing in type 'GoodInterface' when I tried. I could add the index signature to the interfaces I plan to use, but I would prefer not to.

Let's say I want to make a function called doThing that takes a generic. When using this function, I intend to manually input the generic with an interface which could have any keys, but the values should always be strings. I would like TypeScript to give me an error if any of the interface's values are not strings, like this:

function doThing<T extends ???> {
  // do a thing
}

interface GoodInterface {
  foo: string
  bar?: string
}

interface BadInterface {
  foo: number
  bar: string
}

doThing<GoodInterface>() // should work
doThing<BadInterface>() // should give a type error

Note that in GoodInterface, the optional bar key with string value is still accepted.

What would the generic have to extend to achieve this behavior? My initial thought was to extend Record<string, string>, but that gave me the error Index signature for type 'string' is missing in type 'GoodInterface' when I tried. I could add the index signature to the interfaces I plan to use, but I would prefer not to.

Share Improve this question asked Feb 7 at 22:36 BlargelBlargel 4211 gold badge3 silver badges11 bronze badges 2
  • What's with the optional key here? Do you want to accept {bar?: string} but reject {bar: string | undefined}? – jcalz Commented Feb 7 at 23:08
  • Either is fine for the purposes of the real implementation of this function. – Blargel Commented yesterday
Add a comment  | 

1 Answer 1

Reset to default 2

This one right here works

Partial is used to indicate that T can extend types with optional properties.

Record is the object type, keyof T are the keys of the generic type T (the keys of the interface that will be passed as a generic argument), string means that the values of properties can only be strings.

declare function doThing<T extends Partial<Record<keyof T, string>>>(): void;

interface GoodInterface {
  foo: string
  bar?: string
}

interface BadInterface {
  foo: number
  bar: string
}

doThing<GoodInterface>() // Works
doThing<BadInterface>() // Types of property 'foo' are incompatible.

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论