Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Enhancement: [consistent-indexed-object-style] forbidden from using the "in" keyword in index signature if Record is preferred #6598

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

Closed
4 tasks done
yeung108 opened this issue Mar 10, 2023 · 2 comments · Fixed by #10160
Labels
accepting prs Go ahead, send a pull request that resolves this issue enhancement: plugin rule option New rule option for an existing eslint-plugin rule locked due to age Please open a new issue if you'd like to say more. See https://typescript-eslint.io/contributing. package: eslint-plugin Issues related to @typescript-eslint/eslint-plugin

Comments

@yeung108
Copy link

yeung108 commented Mar 10, 2023

Before You File a Proposal Please Confirm You Have Done The Following...

My proposal is suitable for this project

  • I believe my proposal would be useful to the broader TypeScript community (meaning it is not a niche proposal).

Link to the rule's documentation

https://typescript-eslint.io/rules/consistent-indexed-object-style/

Description

When "record" option is chosen in @typescript-eslint/consistent-indexed-object-style, we should also be forbidden from using the "in" keyword in index signature. It's particularly useful for literal types.

Here's the justification:

  • we should prefer Record versus Index Signature whenever we want to use literal types, as index signature accepts only string, number or symbol as key type.
  • And when Record is preferred, it also brings an advantage of ensuring no missing property in literal types -> which further ensures type safety, and avoid getting unexpected undefined case from non-existing key.
  • However, such advantage will not be kept since the current @typescript-eslint/consistent-indexed-object-style rule allows people using { [key in Option] : string}

Fail

/* eslint @typescript-eslint/consistent-indexed-object-style: ["error", "record"] */

type Option = "red" | "yellow";

const optionToString: { [key in Option]: string} = {
   "red": "this is red" // won't be warned that "yellow" is missing
}

Pass

/* eslint @typescript-eslint/consistent-indexed-object-style: ["error", "record"] */

type Option = "red" | "yellow";

// if we use Record, it will prompt error if any property is missing; 
// E.g. it should say "Property 'yellow' is missing in type '{ red: string; }' but required in type 'Record<Option, string>'." 
// if we just have "red" as the only property.
const optionToString: Record<Option, string> = {
   "red": "this is red",
   "yellow": "this is yellow",
}


// Or, if we indeed want to get undefined for some keys; making them explicit when defining
// the type and value is better and clearer.
const optionToString: Record<Option, string | undefined> = {
   "red": "this is red",
   "yellow": undefined,
}

Additional Info

No response

@yeung108 yeung108 added enhancement: plugin rule option New rule option for an existing eslint-plugin rule package: eslint-plugin Issues related to @typescript-eslint/eslint-plugin triage Waiting for team members to take a look labels Mar 10, 2023
@yeung108 yeung108 changed the title Enhancement: [consistent-indexed-object-style] <a short description of my proposal> Enhancement: [consistent-indexed-object-style] forbidden from using the "in" keyword in index signature if Record is preferred Mar 10, 2023
@bradzacher
Copy link
Member

I'm surprised that we don't currently handle this case because Record is literally defined as type Record<K, V> = { [Key in K]: V }.

So I think adding support would be good!

@bradzacher bradzacher added accepting prs Go ahead, send a pull request that resolves this issue and removed triage Waiting for team members to take a look labels Mar 13, 2023
@kirkwaiblinger
Copy link
Member

I'm a little confused because it appears that TS does give an error in the "Fail" case, for all the version and configs that I tried at least. For example, TS 3.3 with all the strict options disabled gives a missing properties error.

Thinking about how we would implement the change to ban mapped types, I'm thinking we might want to try to only flag on "trivial" mapped types, like so:

type Option = "number" | "string";
// should flag
type ShouldBeARecord = { [key in Option]: string }
// should not flag - modifiers are used
type MappingUsesModifier = { readonly [key in Option]?: string }
// should not flag - uses key in mapped type
type UsesKey  = { [key in Option]: key extends "number" ? number : key extends "string" ? string : never  } 

Would maintainers agree?

@github-actions github-actions bot added the locked due to age Please open a new issue if you'd like to say more. See https://typescript-eslint.io/contributing. label Oct 31, 2024
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Oct 31, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
accepting prs Go ahead, send a pull request that resolves this issue enhancement: plugin rule option New rule option for an existing eslint-plugin rule locked due to age Please open a new issue if you'd like to say more. See https://typescript-eslint.io/contributing. package: eslint-plugin Issues related to @typescript-eslint/eslint-plugin
Projects
None yet
3 participants