If your type is guaranteed to be MyDto you can fix your issue with the 'keyof' type operator:
private doSomething(dto: MyDTO, property: keyof MyDTO): string {
let label: any;
if (['dcr', 'ddm'].includes(property)) {
label = doSomethingElse(dto[property]);
} else {
label = dto[property];
}
return label;
}
This way, only string keys of MyDto will be allowed to be passed to your function.
If you can't guarantee the property value type (at compilation time), since you are receiving it from a external source for example you can do the following to correct index the type:
function isKeyOfType<T extends Record<string, any>>(obj: T, property: unknown): property is (keyof T) {
// REMINDER! 'in' operator only works with Objects, because it's similar to check using '.hasOwnProperty'
return typeof property === 'string' && property in obj;
}
private doSomething(dto: MyDTO, property: string): string {
let label: any;
if (!isKeyOfType(dto, property)) {
return ''; // Validate Exceptions
}
if (['dcr', 'ddm'].includes(property)) {
label = doSomethingElse(dto[property]);
} else {
label = dto[property];
}
return label;
}
This is possible because since typescript v3.7 (see release notes) it's possible to create user type guards for narrowing type inference in TypeScript code.
Also you can use the 'in' keyword that also narrow the type to help you validate manually the object in the guard in a runtime type safe way. However it's important to remember that in a production environment sometimes could be a better solution rely in a solution like zod, ajv.js or even class-validator/transformer, for schema/object validation.
The only other thing you need to assert in this case is to remember that if the property is not defined in the object, this will fail because the property is not in the runtime object. But this is easy to solve, one way you can solve that is using a object with all the default values of your interface (convert it to a class), or ignore this validation section and just return true for the assertion and it'll work.
Other Sources: