Reputation: 224
I'm switching from JavaScript to TypeScript, everything was going okay until I entered in this situation. I set my interface in this way:
interface StreamCreateProps {
[title: string]: any
};
My code is:
const validate = (formValues: any) => {
const errors = {};
if(!formValues.title) {
errors.title = 'You must enter a title';
};
if(!formValues.description) {
errors.description = 'You must enter a description';
};
return errors;
};
How can I type the errors.title and errors.description correctly? The full error is: Property 'title' does not exist on type '{}'.
Upvotes: 1
Views: 2123
Reputation: 7226
Use the Record
utility type:
const errors: Record<string, string> = {};
errors.foo = 'okay';
When you declare a variable without specifying the type, you cause the TypeScript Compiler to infer its type for you. The compiler will choose a reasonably narrow type. A few examples:
const foo = false // false
foo = true // ERROR
// `foo` is constant, so TS infers `false`, the only possible value.
let foo = false // boolean
foo = true // OK
foo = 100 // ERROR
// Using `let` or `var` will result in `foo` being reassignable,
// so it could technically be anything;
// however, TS assumes a narrower type based on its initial value.
// `foo` is constant, but it's properties are not,
// so, like with the previous row, `bar` is assignable to any boolean.
const foo = { bar: false } // { bar: boolean; }
foo.bar = true // OK
foo.bar = 100 // ERROR
// a `const` litteral declaration:
// foo and its subproperties should retain the narrowest possible type.
const foo = { bar: false } as const // { readonly bar: false; }
foo.bar = false // ERROR
So applied to your situation:
const foo = {} // {}
foo.bar = 'baz' // ERROR: Property 'bar' does not exist on type '{}'
foo
is too narrow to accept additional properties. Record<string, string>
is less restrictive: it ensures you retain something like { [key: string]: string }
. If you need to work with non-string values, you could widen it further: Record<string, string | number>
or Record<string, any>
.
Upvotes: 1