Take the following example:
type A<Keys extends string, Prefix extends string> =
{[K in Keys]: `${Prefix}-${K}`}
function noGood<K extends string, Prefix extends string>(
obj: A<K, Prefix>, prefix: Prefix
) {
// ...
}
const test: A<'one' | 'two', 'prefix'> = {"one": 'prefix-one', "two": 'prefix-two'}
noGood(test, 'desired to only be "prefix-one" or "prefix-two", but can be any string...')
You can see that the generic types of noGood are inferred from the first param (obj
). Then, when you provide a string to the second param (prefix
)
Obviously you could type out your call to noGood
and it would disallow that random string for the second parameter, but ideally you wouldn't have to.
CodePudding user response:
@HelloWorld per your comment on my other answer, if you want the parameter prefix
to only be a value at one of the keys of the object, it is still relatively easy with some tweaks:
const foo = {"one": 'prefix-one' as const, "two": 'prefix-two' as const}
function noGood<O extends {}>(
obj: O, prefix: O[keyof O]
) {
// ...
}
noGood(foo, 'prefix-one'); // sure ok
noGood(foo, 'crabapple'); // error!
Note the use of as const
when defining the values inside of foo
. This is important because it tells TypeScript that those are values will not change and can be treated as a constant, explicit type and not just any old string
. Otherwise, noGood(foo, 'crabapple')
would not give an error because TypeScript normally would infer the values at each key of foo
as a string
and not "prefix-one" | "prefix-two"
.
If this still doesn't meet your use case, please update your question with more specific details and requirements.
CodePudding user response:
This is trivial at a basic level if you don't care too much about constraining the object parameter of "noGood()
". Use generics to enforce that the parameter prefix
is a key of the object parameter obj
(the word "prefix" seems like a misnomer here since you seem to only care about the keys of obj
but I digress):
function noGood<O extends{}>(
obj: O, prefix: keyof O
) {
// ...
}
There is not really a way that I know of to extract the type information for "Prefix
" from your type A
because that generic type information is not retained by the object after you instantiate it -- there is just no way to enforce that the object passed in as obj
is definitely an instance of your type A
.