- Published on
TypeScript Error: Type string | undefined is not assignable to type string
Resolving Typescript's TS2322 on wrong assignments
Note: TS2322: Type 'string | undefined' is not assignable to type 'string'. Type 'undefined' is not assignable to type 'string'.
Table of Contents
- Resolving Typescript's TS2322 on wrong assignments
- 1.Type guarding the variable
- 2.Non-null assertion operator 'variable!'
- 3.Type Assertion 'variable as sometype'
- 4a.Default Value: with the Logical OR operator '||'
- 4b.Default Value: with the Nullish coalescing '??'
- 4c.Default Value: with The Ternary operator 'condition ? exprIfTrue : exprIfFalse'
Problem Description:
The error message TS2322 indicates that there is a type mismatch in the assignment of a variable. A potential problem arises when we try to assign a variable with a 'narrow' type to a Union Type variable, and we should be careful to avoid this pitfall in TypeScript.
In this case, the type of the variable is string | undefined
, which means that it can either be a string or undefined. However, the type of the variable being assigned to, it requires a strict string
type, meaning it must be a string and cannot be undefined.
Example case:
The example below its showcasing a type mismatch while we are trying to set colorDisplayName
which is of type string and the name
is a superset which also could be undefined.
interface Color {
name?: string
hex: string
rgb: string
}
const myColor: Color = {
name: 'rgb(0, 191, 255)',
hex: '#00bfff',
rgb: 'rgb(0, 191, 255)',
}
const colorDisplayName: string = myColor.name //🚫 ERROR ts(2223)
Solutions:
There are several ways to resolve this error, depending on the context and requirements of our code.
In order to tackle such cases we either need both variables to have all exact same types as a match; or we can omit a type in some cases; like for example when we have undefined
as a secondary type.
Here are some possible solutions:
1.Type guarding the variable
A type guard is a way to check the type of variable before using it in our code. In this case, we can use a type guard to check if the variable is being defined before assigning it to a string colorDisplayName
.
interface Color {
name?: string
hex: string
rgb: string
}
const myColor: Color = {
name: 'rgb(0, 191, 255)',
hex: '#00bfff',
rgb: 'rgb(0, 191, 255)',
}
if (myColor.name !== undefined) {
const colorDisplayName: string = myColor.name
}
2.Non-null assertion operator 'variable!'
The Non-null assertion operator is a post-fix operator that can assert that our variable is non null, and we can access name
. If we are confident the variable will never be undefined, we can use a non-null assertion operator to force TypeScript to treat the variable as a non-null value.
interface Color {
name?: string
hex: string
rgb: string
}
const myColor: Color = {
name: 'rgb(0, 191, 255)',
hex: '#00bfff',
rgb: 'rgb(0, 191, 255)',
}
const colorDisplayName: string = myColor.name!
Warning: This solution would be preferred when we are sure the incoming variable will always be populated.
3.Type Assertion 'variable as sometype'
The Type assertions basically is been used to instruct Typescript at compile-time the exact type to be used. And in our example is no diferent than the Non-null operator where we are forcing the type we want by omitting the case that the variable can be undefined.
interface Color {
name?: string
hex: string
rgb: string
}
const myColor: Color = {
name: 'rgb(0, 191, 255)',
hex: '#00bfff',
rgb: 'rgb(0, 191, 255)',
}
const colorDisplayName: string = myColor.name as string
4a.Default Value: with the Logical OR operator '||'
With the Logical OR we can act in the similar way with the Nullish coalescing operator by in this case we cover more scenarios and not only null
or undefined
, but also empty ''
,false
,0
, and NaN
interface Color {
name?: string
hex: string
rgb: string
}
const myColor: Color = {
name: 'rgb(0, 191, 255)',
hex: '#00bfff',
rgb: 'rgb(0, 191, 255)',
}
const colorDisplayName: string = myColor.name || ''
4b.Default Value: with the Nullish coalescing '??'
We can use nullish coalescing as a fallback mechanism when our variable is null
or undefined
, then we can set some default value, so it will comply the string only restriction.
interface Color {
name?: string
hex: string
rgb: string
}
const myColor: Color = {
name: 'rgb(0, 191, 255)',
hex: '#00bfff',
rgb: 'rgb(0, 191, 255)',
}
const colorDisplayName: string = myColor.name ?? ''
4c.Default Value: with The Ternary operator 'condition ? exprIfTrue : exprIfFalse'
With the Ternary operator we can type guard and assert the possibility of placing an undefined value into out variable colorDisplayName
interface Color {
name?: string
hex: string
rgb: string
}
const myColor: Color = {
name: 'rgb(0, 191, 255)',
hex: '#00bfff',
rgb: 'rgb(0, 191, 255)',
}
const colorDisplayName: string = myColor.name ? myColor.name : ''
Warning: Using default value to tackle that issue might not be always the preferred choice.
Summary:
we can resolve TS2322 with:
- Type guard
- Non-null Assertion
- Type Assertion
- Default Value