Home > Mobile >  TypeScript - type cast not returning falsey value as expected
TypeScript - type cast not returning falsey value as expected

Time:05-09

I would like the casting of a string at runtime to return a falsey value if the type is mismatched. Namely, when I run the following with [email protected], I encounter unexpected results:

$ ts-node
> 0 as 'B' | 'C' | 'D' || 'foo'         // ✅ throws precompiler error as expected
--------------
> '' as 'B' | 'C' | 'D' || 'foo'        // ✅ prints 'foo' as expected
'foo' 
> undefined as 'B' | 'C' | 'D' || 'foo' // ✅ prints 'foo' as expected
'foo' 
> null as 'B' | 'C' | 'D' || 'foo'      // ✅ prints 'foo' as expected
'foo' 
> 'B' as 'B' | 'C' | 'D' || 'foo'       // ✅ prints 'B' as expected
'B' 
> 'A' as 'B' | 'C' | 'D' || 'foo'       // ❌ prints 'A' instead of 'foo' <-- UNEXPECTED
'A'

I clearly misunderstand how casting works, but how do I implement the logic I am trying to achieve where I expected 'A' as 'B' | 'C' | 'D' to return a falsey value?

CodePudding user response:

as is a type assertion, it does not have a runtime effect. You need to do some manual checking of the value instead. Something like:

const allowed = new Set(['B', 'C', 'D']);
const input: string = 'A';
const value = allowed.has(input) ? input : 'foo';

You then can assert that value is 'B' | 'C' | 'D' | 'foo' using as.

Playground (runnable)
Playground using type-fu to not repeat literals

CodePudding user response:

The "cleanest" way to work with unknown literals in my opinion is using a type guard.

type YourLiteralType = 'B' | 'C' | 'D'

// Important part is the return type, and returning a boolean value
function isYourLiteralType(input: unknown): input is YourLiteralType {
  return input === 'B' || input === 'C' || input === 'D'
}

const a = 'A'

// Works with ifs
if (isYourLiteralType(a)) {
  // a is "casted" to YourLiteralType
}


function doSomethingWithYourLiteralType(input: YourLiteralType) {
  // Raises a compiler error if not called with the appropriate type
}

// Also works with ternaries
const x = isYourLiteralType(a) ? doSomethingWithYourLiteralType(a) : undefined
  • Related