Home > Net >  TS strictNullChecks false different behaviour in conditional type
TS strictNullChecks false different behaviour in conditional type

Time:01-26

I have the following function:

interface BaseOptions {
  prefix?: string;
}

function foo<T extends BaseOptions>(options?: T): T['prefix'] extends string ? 1 : 2 {
  return 1 as any;
}

When using strictNullChecks: true I get the expected type result:

// strictNullChecks: true
const v1 = foo(); // 2
const v2 = foo({ prefix: 'bar' }) // 1

But when using strictNullChecks: false it's broken:

// strictNullChecks: false
const v12 = foo(); // 1
const v22 = foo({ prefix: 'bar' }) // 1

What's the reason for this behaviour and how can I fix it?

CodePudding user response:

Without strict null checks a type like string allows within it's definition the values null and undefined, so the type of the optional property will changed from string | undefined with strict null checks, to just string without that option (since undefined is just absorbed in to string).

This means that without strict null checks, BaseOptions['prefix'] extends string resolves to string extends string which is always true, while with strict null checks it resolves to BaseOptions['prefix'] extends string resolves to string | undefined extends string which is false.

You could use a default of never for the type parameter and test for never instead:

function foo<T extends BaseOptions = never>(options?: T): [T] extends [never] ? 2 : 1 {
  return 1 as any;
}

Playground Link

Or if you want to check specifically for the property, you could also use keyof:

function foo<T extends BaseOptions = never>(options?: T): keyof T extends 'prefix' ? 1 : 2 {
  return 1 as any;
}

Playground Link

  •  Tags:  
  • Related