I have a simple Typescript function like this:
function getProperty<T, K extends keyof T>(obj: T, key: K): number {
return obj[key]; // This line is not compiling.
// Typescript will yell: "Type 'T[K]' is not assignable to type 'number'."
}
My usage looks like this:
const someObj = {
myValue: 123,
otherProperty: '321'
}
getProperty(someObj, 'myValue')
I won't know what structure of someObj
will be.
My question is: How can I specify that T[K]
is number type statically?
I won't know what structure of
someObj
will be.
Then TypeScript can't really help you with this. TypeScript's type checking is done at compile-time. If the structure of someObj
will only be known at runtime, TypeScript can't make access to that structure typesafe. You'd need to know what the property keys and possible values for those properties are at compile-time.
For instance: In your example, the property names are strings and the property values are either strings or numbers (but not booleans or objects, etc.). You can declare a type indexed by strings (since all property names are ultimately strings or Symbols, in this case strings) where the property values are numbers or strings:
declare type SomeObjType = {
[key: string]: number | string
};
and then getProperty
is:
function getProperty<T extends SomeObjType>(obj: T, key: string): number | string {
return obj[key];
}
and you can use it like this (in this case, I use JSON.parse
to simulate receiving this data from outside the scope of the program):
const someObj: SomeObjType = JSON.parse(`{
"myValue": 123,
"otherProperty": "321"
}`);
console.log(getProperty(someObj, 'myValue'));
console.log(getProperty(someObj, 'otherProperty'));
But that doesn't buy you much, and closes off the possibility that the property values are something other than numbers or strings.
You may need to just use object
:
function getProperty(obj: object, key: string) {
return obj[key];
}
const someObj = JSON.parse(`{
"myValue": 123,
"otherProperty": "321"
}`);
console.log(getProperty(someObj, 'myValue'));
console.log(getProperty(someObj, 'otherProperty'));