-
Notifications
You must be signed in to change notification settings - Fork 12.8k
keyof typeof Partial Record #35981
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
Why do you think only
And |
Hmm, I was going to say it looks like you expect Or, another way of looking at this: you don't want to annotate const a = ['test', 'test2'] as const;
const b = { // no annotation
test2: 'ads',
} as const;
interface Props {
size: keyof typeof b; // "test2"
}
// ensure assignability later, if it matters
const ifItMatters: Partial<Record<typeof a[number], any>> = b; // okay |
@AnyhowStep @jcalz |
This is all working as intended; it's not a bug in the compiler. If In your updated example, that means I showed one way to avoid that issue before with const sizes = ['small', 'medium', 'large'] as const;
// helper function that ensures assignability without type annotation
const asButtonSizeObj = <T extends Partial<Record<typeof sizes[number], any>>>(t: T) => t;
// buttonSize will be of type `{small: string, large: string}` now
const buttonSize = asButtonSizeObj({
small: '20px',
large: '20px'
});
interface IButtonProps {
size: keyof typeof buttonSize; // "small" | "large"
} |
@jcalz Isn't one of the ideas of |
The only downside to the const sizes = ['small', 'medium', 'large'] as const;
// helper function that ensures assignability without type annotation
const asButtonSizeObj = <T extends Partial<Record<typeof sizes[number], any>>>(t: T) => t;
// buttonSize will be of type `{small: string, large: string}` now
const buttonSize = asButtonSizeObj({
small: '20px',
large: '20px',
extraProp0 : "boo",
});
interface IButtonProps {
//"extraProp0" probably unintended
size: keyof typeof buttonSize; // "small" | "large" | "extraProp0"
} There's a workaround for that downside, const sizes = ['small', 'medium', 'large'] as const;
// helper function that ensures assignability without type annotation
const asButtonSizeObj = <T extends Partial<Record<typeof sizes[number], any>>>(t: T) : (
{
[k in Extract<keyof T, typeof sizes[number]>] : T[k]
}
) => t;
// buttonSize will be of type `{small: string, large: string}` now
const buttonSize = asButtonSizeObj({
small: '20px',
large: '20px',
extraProp0 : "boo",
});
interface IButtonProps {
size: keyof typeof buttonSize; // "small" | "large"
} But these workarounds inside workarounds just make me uneasy. Another workaround is to forbid these extra properties (essentially, add excess prop checks again, which generics remove), but I find that workaround is pretty brittle |
@AnyhowStep Do you mind sending me material about how you've done this, and why isn't
Mind showing me how this is done? This is exactly the last piece I'm missing. |
This issue has been marked as 'Question' and has seen no recent activity. It has been automatically closed for house-keeping purposes. If you're still waiting on a response, questions are usually better suited to stackoverflow. |
TypeScript Version: 3.5.1
Search Terms:
Partial, keyof, typeof, Record, nested object
As a part of a design system I'm making, I want to create a list of sizes that a component may define for itself.
Say I have a list of
small
,medium
,large
.Now I want to define an object mapping one the above sizes to the actual size like
I want that object to enforce using keys from the list of sizes, and then to enforce the consumer of the property to pass only defined sizes (that is
small
andlarge
).The best I came up with is to say that
buttonSize
is an object built from some ofsizes
.This however could not limit the option for the consumer (see below snippet).
Seems like trying to get the keys of the
buttonSize
was just delegating you tosize
.Either there is an issue here, or I completely misunderstood this usage of the types.
Code
Expected behavior:
Only
small | large
should be allowed insize
property (not allowingmedium
)Actual behavior:

Every one of the sizes is allowed (
small | medium | large
).Related Issues:
This might relate
The text was updated successfully, but these errors were encountered: