Aaron Beall
Aaron Beall

Reputation: 52143

Is it possible to validate strings as property names of interface?

Suppose I have an interface like this:

interface User {
    id: string;
    name: string;
    age: number;
}

And I have a method like this:

function getUserValues(properties:string[]):void {
    Ajax.fetch("user", properties).then((user:User) => alert(user));
}

And a good call looks like this:

getUserValues("id", "name", "age");

But this will lead to an error:

getUserValues("bogus", "stuff", "what_even_am_i_doing");

What I want is to validate that properties contains only valid property names of the User interface. Is this possible? Is there some other way to achieve the safety I'm after here?

Upvotes: 0

Views: 520

Answers (2)

NagRock
NagRock

Reputation: 325

You can use keyof to achieve this:

function get<T, K extends keyof T>(obj: T, propertyName: K): void { ... };

Upvotes: 1

basarat
basarat

Reputation: 275917

What I want is to validate that properties is only valid property names of the User interface. Is there some other way to achieve the safety I'm after here?

You need string literal types in a union:

function getUserValues(properties:('id'|'name'|'age')[]):any[] {
    Ajax.fetch("user", properties).then((user:User) => alert(user));
}

You can use code generation to generate the union type from the interfaces for you.

More

https://basarat.gitbooks.io/typescript/content/docs/types/stringLiteralType.html

Automatically by interface

Can't be done at the moment. That is no declarative way to say "valid property names of this interface are the members of this string literal union". One can generate code to do the following:

interface User {
    id: string;
    name: string;
    age: number;
}
// Generated. Or kept in sync with the `User` interface manually 
type UserPropertyNames = 'id' | 'name' | 'age';

Upvotes: 0

Related Questions