TypeScript Version: 3.5.1, 3.7.2
Search Terms:
Force TS to alias type, optional property, type expand
Code
type Identity<T> = T;
type PleaseDoNotExpand<T> =
| T
| { x : T }
;
type MappedType<ObjT> =
Identity<
& {
readonly [k in Exclude<keyof ObjT, "x">]: (
PleaseDoNotExpand<ObjT[k]>
)
}
& {
readonly [k in Extract<keyof ObjT, "x">]?: (
PleaseDoNotExpand<ObjT[k]>
)
}
>
;
declare function mappedType<ObjT>(obj: ObjT): MappedType<ObjT>;
/*
Expected:
const x: {
readonly y: PleaseDoNotExpand<string>;
readonly z: PleaseDoNotExpand<boolean>;
} & {
readonly x?: PleaseDoNotExpand<number>|undefined;
}
*/
/*
Actual:
const x: {
readonly y: PleaseDoNotExpand<string>;
readonly z: PleaseDoNotExpand<boolean>;
} & {
readonly x?: number | {
x: number;
} | undefined;
}
*/
const x = mappedType({
x: 1,
y: "hi",
z: true,
});
Expected behavior:
Expected x to resolve to,
const x: {
readonly y: PleaseDoNotExpand<string>;
readonly z: PleaseDoNotExpand<boolean>;
} & {
readonly x?: PleaseDoNotExpand<number>|undefined;
}
Actual behavior:
Actually resolves to,
const x: {
readonly y: PleaseDoNotExpand<string>;
readonly z: PleaseDoNotExpand<boolean>;
} & {
readonly x?: number | {
x: number;
} | undefined;
}
This behaviour is caused by the ? optional property modifier. It seems to do something that messes up emit, and makes it inconsistent with required properties.
Since required properties do not expand the PleaseDoNotExpand<> type,
optional properties should also not expand the PleaseDoNotExpand<> type.
I believe this is a bug in emit.
Playground Link:
Playground
Related Issues:
Kind of related to this,
#34556
That issue wants a way to future-proof ways of forcing TS to not alias a type.
The Identity<> trick works nicely at the moment.
Also related to this,
#34777
#34777 (comment)
That issue wants a way to force TS to always alias a type.
There is a workaround using interface when the properties are always known and you do not have union types.
It does not apply in this case, because I have union types.
This mini-rant probably belongs in a different issue but...
I would like a way to have TS never expand a type alias for hover tooltip and emit.
Not by default, anyway.
My actual PleaseDoNotExpand<> type is easily 100+ lines long. It makes everything unreadable, when TS fully expands it.
I can read PleaseDoNotExpand<Date> better than I can read the following,
readonly createdAt?: Date | tsql.IExpr<{
mapper: Mapper<unknown, Date>;
usedRef: tsql.IUsedRef<{}>;
}> | (tsql.IQueryBase<{
fromClause: tsql.IFromClause<tsql.FromClauseData>;
selectClause: [tsql.IColumn<{
tableAlias: string;
columnAlias: string;
mapper: Mapper<unknown, Date>;
}> | tsql.IExprSelectItem<{
mapper: Mapper<unknown, Date>;
tableAlias: string;
alias: string;
usedRef: tsql.IUsedRef<never>;
}>];
limitClause: tsql.LimitClause | undefined;
compoundQueryClause: readonly tsql.CompoundQuery[] | undefined;
compoundQueryLimitClause: tsql.LimitClause | undefined;
mapDelegate: tsql.MapDelegate<never, never, unknown> | undefined;
}> & tsql.IQueryBase<{
fromClause: tsql.IFromClause<{
outerQueryJoins: readonly tsql.IJoin<tsql.JoinData>[] | undefined;
currentJoins: undefined;
}>;
selectClause: readonly (tsql.ColumnMap | tsql.IColumn<tsql.ColumnData> | tsql.IExprSelectItem<tsql.ExprSelectItemData> | tsql.ColumnRef)[] | undefined;
limitClause: tsql.LimitClause | undefined;
compoundQueryClause: undefined;
compoundQueryLimitClause: tsql.LimitClause | undefined;
mapDelegate: tsql.MapDelegate<never, never, unknown> | undefined;
}> & tsql.IQueryBase<{
fromClause: tsql.IFromClause<{
outerQueryJoins ...
TypeScript Version: 3.5.1, 3.7.2
Search Terms:
Force TS to alias type, optional property, type expand
Code
Expected behavior:
Expected
xto resolve to,Actual behavior:
Actually resolves to,
This behaviour is caused by the
?optional property modifier. It seems to do something that messes up emit, and makes it inconsistent with required properties.Since required properties do not expand the
PleaseDoNotExpand<>type,optional properties should also not expand the
PleaseDoNotExpand<>type.I believe this is a bug in emit.
Playground Link:
Playground
Related Issues:
Kind of related to this,
#34556
That issue wants a way to future-proof ways of forcing TS to not alias a type.
The
Identity<>trick works nicely at the moment.Also related to this,
#34777
#34777 (comment)
That issue wants a way to force TS to always alias a type.
There is a workaround using
interfacewhen the properties are always known and you do not have union types.It does not apply in this case, because I have union types.
This mini-rant probably belongs in a different issue but...
I would like a way to have TS never expand a type alias for hover tooltip and emit.
Not by default, anyway.
My actual
PleaseDoNotExpand<>type is easily 100+ lines long. It makes everything unreadable, when TS fully expands it.I can read
PleaseDoNotExpand<Date>better than I can read the following,