Typescript: Mapped types shouldn't transform unknown type

Created on 7 Feb 2019  路  4Comments  路  Source: microsoft/TypeScript

@ahejlsberg Probably #29740 made this regression.


TypeScript Version: 3.4.0-dev.20190207


Search Terms:

Code

type DeepReadonly<T> =
  T extends void ? T :
  { readonly [P in keyof T]: DeepReadonly<T[P]>; };
type m = { a: unknown }; // Also unknown[].
type i = DeepReadonly<m>;

Expected behavior:

i is { readonly a: unknown; }.

Actual behavior:

i is { readonly a: {}; }.

Playground Link:

Related Issues:

Suggestion

Most helpful comment

The essential issue is mapped types replace unknown type with {} type as follows:

type Mapped<T> =
  { [P in keyof T]: T[P]; };
type a = Mapped<unknown>;

Conditional types are not related.

The difference of the behavior since that day is the return type of DeepReadonly<unknown[]> is changed from any[] to {}[]. Conditional types are needed for this behavior but not essential.

All 4 comments

@falsandtru Doesn't seem to have to do with it being recursive, unknown is mapped to {} in simple mapped types and in 3.3 as well so its probably not related to #29740

type Mapped<T> = { [P in keyof T]: T[P] }

type m_unknown = Mapped<unknown> // {}
type m_any = Mapped<any> // { [x: string]: any; }
type m_never = Mapped<never> // never 

This is definitely not a regression, mapped types have behaved this way since the introduction of the unknown type. That said, it might be more consistent to map unknown to unknown as it would better preserve the top-type aspect of unknown.

@ahejlsberg I judged that this is a regression since the following code make an error since 3.4.0-dev.20190207:

https://github.com/falsandtru/spica/blob/v0.0.222/src/type.test.ts#L368

The essential issue is mapped types replace unknown type with {} type as follows:

type Mapped<T> =
  { [P in keyof T]: T[P]; };
type a = Mapped<unknown>;

Conditional types are not related.

The difference of the behavior since that day is the return type of DeepReadonly<unknown[]> is changed from any[] to {}[]. Conditional types are needed for this behavior but not essential.

Was this page helpful?
0 / 5 - 0 ratings