In TypeScript, I declare an interface like this:
export default interface MyDTO {
readonly num: string;
readonly entitle: string;
readonly trb: st
@mhodges, with your suggestions, here is my modified function which seems to work well. However in the following case, I had to add the "as string" otherwise I have the following error:
Type 'string | keyof V 'cannot be used to index type' V'.ts (2536)
public getDefaultComparator(property: keyof V | string, v1: V, v2: V): number {
let compareReturn = 0;
if (v1.hasOwnProperty(property)) {
const compareValue1 = v1[property as string];
const compareValue2 = v2[property as string];
if (compareValue1 > compareValue2) {
compareReturn = 1;
} else if (compareValue1 < compareValue2) {
compareReturn = -1;
}
}
return compareReturn;
}
The reason for this is because MyDTO
has explicitly named properties, but you're using a generic string as an index, so TypeScript is saying that it can't guarantee that whatever string is passed into your doSomething
function will actually match a property name on your interface.
An excellent workaround for this that was introduced in TypeScript 2.1 is keyof
. This allows you to explicitly type something as a key of a certain class/interface.
This will A. get rid of the TS error you're seeing, and B. also check to make sure that any callers of your function actually pass a valid key.
export default interface MyDTO {
readonly num: string;
readonly entitle: string;
readonly trb: string;
readonly ucr: string;
readonly dcr: string;
readonly udm?: string;
readonly ddm?: string;
}
function doSomething(dto: MyDTO, property: keyof MyDTO): any {
let label: any;
if (['dcr', 'ddm'].includes(property)) {
label = doSomethingElse(dto[property]);
} else {
label = dto[property];
}
return label;
}
doSomething(obj, "foo") // is a TS error
doSomething(obj, "num") // is valid