Anton
Anton

Reputation: 576

Why property type unassignalbe while passing via const in TypeScript?

I know this is 100% a noob question, but i can't handle myself and want to know an answer.

type SweetAlertPosition =
    'top' | 'top-start' | 'top-end' | 'top-left' | 'top-right' |
    'center' | 'center-start' | 'center-end' | 'center-left' | 'center-right' |
    'bottom' | 'bottom-start' | 'bottom-end' | 'bottom-left' | 'bottom-right';

Main interface(simplified):

interface SweetAlertOptions {
    ...,
    position?: SweetAlertPosition
}
class Swal {
    mixin(options: SweetAlertOptions)
}

Now, if i explicitly pass options to .mixin call: Swal.mixin({ position: 'bottom' }) - no error is there. But if i predefine options in some const object:

defaultOptions = {
   position: 'bottom'
}

Passing now make an error - Swal.mixin(defauiltOptions)

Types of property 'position' are incompatible.
Type 'string' is not assignable to type '"top" | "top-start" | "top-end" | "top-left" | "top-right" | "center" | "center-start" | "center-end" | "center-left" | "center-right" | "bottom" | "bottom-start" | "bottom-end" | "bottom-left" | "bottom-right" | undefined'.

I already found out that a have to cast String type to const:

defaultOptions = {
    position: 'botton' as const | as SweetAlertPosition
}

But why passing options via const obj(defaultOptions) make position property become String-type, and passing it directly does not oO ?

Upvotes: 0

Views: 237

Answers (2)

Bergi
Bergi

Reputation: 664548

When declaring a const variable, its type is derived only from the value you assign to it, not from where the variable is used (full type inference). When initialising a variable with an object literal, the property types are widened so that you might assing other strings or numbers to them - unless you narrow them with as const.

When passing an object literal as an argument, its type is inferred from the parameter types of the called function.

In your case, I wouldn't write as const but recommend

const defaultOptions: SweetAlertOptions = {
   position: 'bottom'
};

Upvotes: 1

crashmstr
crashmstr

Reputation: 28573

The problem is that defaultOptions has a type of { position: string } unless you do something about it, like this:

const defaultOptions: SweetAlertOptions = {
   position: 'bottom'
}

Here, we explicitly declare that defaultOptions is of type SweetAlertOptions and then there is no error when passing into mixin.

In the example of passing in the value explicitly, the compiler can interpret the object in the context of the call.

Example in TypeScript Playground

Upvotes: 1

Related Questions