I've gotten this far: which seems to work
function test<types extends Record<string,any>>(dict: dictionary<types>){}
type dictionary<types extends Record<string, any>> = {
[key in keyof types]: {
bar?: types[key];
foo?: (value:types[key])=>true;
};
};
test({
key1:{
bar: 2,
foo: (input:number)=>true,
},
key2:{
bar: 'hello'
foo: (input: number)=>true, // Error! "input" needs to be string
}
})
BUT!
I also need a generic type reference to the dict
parameter. And for some reason, this doesn't work
function test2<
types extends Record<string,any>,
dictionary extends dictionary2<types> // <-- Added a generic type
>(dict: dictionary){}
// Same as above
type dictionary2<types extends Record<string, any>> = {
[key in keyof types]: {
bar?: types[key];
foo?: (value:types[key])=>true;
};
};
// Same as above
test2({
key1:{
bar: 2,
foo: (input: number)=>true,
},
key2:{
bar: 'hello',
foo: (input:number)=>true,// Should be an Error (but isn't)! "input" needs to be string
}
CodePudding user response:
You could do like this:
function test2<T extends Record<string, unknown>>(dict: Dictionary<T>) { }
type Dictionary<T> = {
[key in keyof T]: {
bar?: T[key];
foo?: (value: T[key]) => true;
};
}
// Same as above
test2({
key1: {
bar: 2,
foo: (input: number) => true,
},
key2: {
bar: 'hello',
foo: (input: number) => true, // Actual error
}
});
CodePudding user response:
Change the inference scope so that types
is inferred and dict
is typed based on that inference rather than a second type parameter, i.e.,
function test2<
types extends Record<string,any>
>(dict: dictionary2<types>){}
Working playground here.
EDIT: Example usage with conventional capitalization
function test2<
T,
>(dict: Dictionary<T>){
type FullDictionary = Dictionary<T> // can't you just use this in your function?
}
type Dictionary<T extends Record<string, any>> = {
[K in keyof T]: DictionaryEntry<T[K]>
}
type DictionaryEntry<T> = {
bar?: T
foo?: (value:T)=>true
}
test2({
key1:{
bar: 2,
foo: (input: number)=>true,
},
key2:{
bar: 'hello',
foo: (input:number)=>true
}
})