Reputation: 21510
I want to specify type in that way, that its generic parameter should be an object that can be parsed from json. So no functions, no dates, no other kinds of values that can't be represented in json. How can I do that?
function get<T>(url: string): Promise<T> {
return fetch(url).then(resp => resp.json())
}
interface Type1 {
x: string;
}
interface Type2 {
x: string;
getX(): string;
}
interface Type3 {
x: Date;
}
interface Type4 {
x: {
a: number[];
b: { z: (string | null)[] };
};
}
async function main() {
var a = await get<Type1>("/")
var b = await get<Type2>("/") // Want a error
var c = await get<Type3>("/") // Want a error
var d = await get<Type4>("/")
}
Upvotes: 4
Views: 149
Reputation: 3855
Try creating an interface for your desired type that specifies a union of all valid types, like this:
interface IJson {
[key: string]: number | string | boolean | Array<number | string | boolean | IJson | null> | IJson | null;
}
Edit: After some research, turns out TypeScript actually provides an example of exactly this on their docs. They recommend this:
type Json =
| string
| number
| boolean
| null
| { [property: string]: Json }
| Json[];
Edit 2: Check out my updated (from yours) sandbox that plays around with some of these things. Unfortunately, it doesn't seem possible to pass an interface argument to T unless the interface also has an index signature, something like { [key: string]: string }
. You should be able to get around this by changing your interface to a type definition, like type Type1 = { x: string }
which should then work just fine. I know it's not exactly what you were looking for but I'm not sure that there's currently (or ever will be) support for that in TypeScript.
Upvotes: 2