Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ability to specify that T[K] extends a type #31325

Closed
Roaders opened this issue May 9, 2019 · 4 comments
Closed

Ability to specify that T[K] extends a type #31325

Roaders opened this issue May 9, 2019 · 4 comments
Labels
Question An issue which isn't directly actionable in code

Comments

@Roaders
Copy link

Roaders commented May 9, 2019

Search Terms

enforce key type of generic type

Suggestion

I would like to specify that a property, defined as a function argument, of a generic type is of a specific type

Use Cases

I want to pass an item and a key to a function and specify that the type of the property specified by the key is a certain type

Examples

function cacheItem<T extends {K: string}, K extends keyof T>(item: T, key: K){
     const key = item[key]; // should be typed as string
}

const myItem = {
    id = "string",
    count = 1234
}

cacheItem(myItem, "id") // works
cacheItem(myItem, "count") // should throw error

Checklist

My suggestion meets these guidelines:

  • [x ] This wouldn't be a breaking change in existing TypeScript/JavaScript code
  • [x ] This wouldn't change the runtime behavior of existing JavaScript code
  • [x ] This could be implemented without emitting different JS based on the types of the expressions
  • [x ] This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, etc.)
  • [ x] This feature would agree with the rest of TypeScript's Design Goals.
@jack-williams
Copy link
Collaborator

Looks related: #31275

@anion155
Copy link

anion155 commented May 9, 2019

function cacheItem<
  T extends any,
  K extends {
    [K in keyof T]: T[K] extends string ? K : never
  }[keyof T]
>(item: T, key: K) {
  const value: string = item[key]; // is typed as string
  value.replace;
}

@jcalz
Copy link
Contributor

jcalz commented May 9, 2019

{K: string} is not saying what you intend to say, since K is just a literal key there (e.g., foo.K = "oops"). Instead, you can use a mapped type such as {[P in K]: string} or the equivalent Record<K, string>. (Eventually you may be able to use K directly as an index signature as in {[k: K]: string} but that is not currently supported.)

@RyanCavanaugh RyanCavanaugh added the Question An issue which isn't directly actionable in code label May 13, 2019
@RyanCavanaugh
Copy link
Member

You don't need new machinery to do this.

function cacheItem<K extends string>(item: Record<K, string>, key: K) {
    const val = item[key]; // should be typed as string (is)
}

const myItem = {
    id: "string",
    count: 1234
}

cacheItem(myItem, "id") // works
cacheItem(myItem, "count"); // Error

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Question An issue which isn't directly actionable in code
Projects
None yet
Development

No branches or pull requests

6 participants