- Sponsor
-
Notifications
You must be signed in to change notification settings - Fork 5k
1367 - Remove Index Signature - Template literal alternative #3542
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
Comments
Can you help me, why it works? |
Sure. Let me break down what is happening here. The whole syntax being used here is key remapping - also used in other solutions. It allows us to change or filter out keysets. In the remap logic, we are determining which keys need to be filtered out via conditional typing: as Key extends `${infer ConcreteKey}` ? ConcreteKey : never We can phrase the logic here like "If the key being remapped is a string literal (or a specific string value instead of the generic As for the condition: Key extends `${infer ConcreteKey}` We are trying to infer if the key can be pulled out of a template literal. From definition, template literals are built on string literal types, which would be the only types you can infer from it and not a generic As to how TS handles these internally, I am not sure about those, the docs I have linked may be able to give insights about it. Hope these help. |
awesome! thanks a lot! |
Wow, the best explanation I've ever seen! Thanks! |
great explanation and thanks for the doc links! |
Hi @ianbunag could you please also explain why Key in keyof Type
|
Hey, my answer is outdated, I would recommend checking this answer as it passes all the latest test cases (even symbols which my answer previously supported).
Here is an example: type DoNothing<Type extends Record<string, unknown>> = {
[Key in keyof Type]: Type[Key]
}
type Base = {
hello: string,
hi: number,
}
/**
* type AllFields = {
* hello: string,
* hi: number,
* }
*/
type AllFields = DoNothing<Base>
type PickNumberFields<Type extends Record<string, unknown>> = {
// Iterate over all keys (Key) of the parameter (Type)
// Then check if the value associated with the current Key in Type is a number
// If it is a number, retain, otherwise filter it out by remapping to never
[Key in keyof Type as Type[Key] extends number ? Key : never]: Type[Key]
}
/**
* type NumberFields = {
* hi: number;
* }
*/
type NumberFields = PickNumberFields<Base> Play with this in TypeScript playground. See this comment for a thorough explanation. |
The text was updated successfully, but these errors were encountered: