microsoft / microsoft/TypeScript
Unexpected type assertion result
Nobody has claimed this yet.
- Dominant language
- Go
- Stars
- 111k
- Forks
- 14.3k
- Avg merge
- 2d 4h
- Merged PRs (30d)
- 132
Description
TypeScript Version: 3.6.0-dev.20190801
Search Terms:
type assertion absolute importtype assertion importtype cast absolute importtype cast importtype assertion pick
Code
Repo: https://github.com/klemenoslaj/typescript-type-assertion
generated/types.d.ts
export interface TypeD {
da: string;
db: string;
dc: string;
}
export interface Test {
a: string;
b: string;
c: string;
d?: { __private: 'd' } & TypeD;
}
src/index.model.ts
import { Test } from 'generated/types';
type DType = NonNullable<Test['d']>;
export type Model = Pick<DType, keyof Exclude<DType, '__private'>>;
src/index.ts
import { Model } from './index.model';
export class A {
value = <Model>{};
}
dist/index.model.d.ts
import { Test } from 'generated/types';
declare type DType = NonNullable<Test['d']>;
export declare type Model = Pick<DType, keyof Exclude<DType, '__private'>>;
export {};
dist/index.d.ts
export declare class A {
value: Pick<{
__private: "d";
} & import("../generated/types").TypeD, "__private" | "da" | "db" | "dc">;
}
Expected behavior:
I would expect that dist/index.d.ts type definitions would result in:
import { Model } from './index.model';
export declare class A {
value: Model;
}
In fact, this is the result of type definitions, if I change value = <Model>{}; to value: Model = <Model>{};.
Why doesn't typescript use Model directly when type asserting?
Actual behavior:
Results in:
export declare class A {
value: Pick<{
__private: "d";
} & import("../generated/types").TypeD, "__private" | "da" | "db" | "dc">;
}
Playground Link:
I couldn't figure out how to compile declarations in playground, sorry :(
As an alternative please clone the following repo: https://github.com/klemenoslaj/typescript-type-assertion
Explanation:
This is quite a significant problem in monorepo environment.
What happens is that projects are compiled in the dist/ folder and they contain relative path like above (import("../generated/types")), which points from the src/ and not from dist/, effectively producing an error when projects start using one another.
Why doesn't typescript:
- use the original path from the import (
generated/types)? - use the type from assertion directly (
Model)?
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Clone the linked repro repository and compile the files under src/ with declarations enabled, then compare dist/index.d.ts with the expected output. Start by tracing declaration generation for the assertion in src/index.ts and the Model type from src/index.model.ts. Done means the generated declaration preserves Model and uses an import path that remains valid from dist/.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 25/100