The question in the title is the current behaviour.
TypeScript Version: 3.2.0-dev.20181027
Relates to: #25731
The compiler API will resolve some, but not all, equivalent types to the first encountered type:
import * as ts from "typescript";
const testFilePath = "/file.ts";
const testFileText = `
export type AvatarSize = 'sm' | 'md' | 'lg' | 'xl';
export type CardAvatarSize = 'sm' | 'md' | 'lg' | 'xl';
let v1: AvatarSize, v2: CardAvatarSize;
`;
// common setup
const testSourceFile = ts.createSourceFile(testFilePath, testFileText, ts.ScriptTarget.Latest);
const variableStatement = testSourceFile.statements.find(ts.isVariableStatement)!;
const variableDeclarations = variableStatement.declarationList.declarations;
// outputs: "AvatarSize", "AvatarSize"
const typeChecker1 = getTypeChecker();
logTypeText(typeChecker1, variableDeclarations[0]);
logTypeText(typeChecker1, variableDeclarations[1]);
// outputs: "CardAvatarSize", "CardAvatarSize"
const typeChecker2 = getTypeChecker();
logTypeText(typeChecker2, variableDeclarations[1]); // note 1, not 0 this time
logTypeText(typeChecker2, variableDeclarations[0]);
function logTypeText(typeChecker: ts.TypeChecker, declaration: ts.VariableDeclaration) {
const type = typeChecker.getTypeAtLocation(declaration.type!);
console.log(typeChecker.typeToString(type));
}
function getTypeChecker() {
const options: ts.CompilerOptions = { target: ts.ScriptTarget.ES5 };
const host: ts.CompilerHost = {
fileExists: filePath => filePath === testFilePath,
directoryExists: dirPath => dirPath === "/",
getCurrentDirectory: () => "/",
getDirectories: () => [],
getCanonicalFileName: fileName => fileName,
getNewLine: () => "\n",
getDefaultLibFileName: () => "",
getSourceFile: filePath => filePath === testFilePath ? testSourceFile : undefined,
readFile: filePath => filePath === testFilePath ? testFileText : undefined,
useCaseSensitiveFileNames: () => true,
writeFile: () => {}
};
return ts.createProgram({
options,
rootNames: [testFilePath],
host
}).getTypeChecker();
}
I found #25731 that says this is a design limitation. What I was wondering is in the context of the compiler API, which people aren't using only for type checking, does it make sense to have this design? When working with the compiler api, I feel like it's valuable to have distinct ts.Type objects whose text will be the name of the type alias used in the situation (ex. when someone does type MyType = string; it would be nice for it to return a MyType ts.Type object instead of the string one). Or does this just increase the complexity too much internally?
Also note that this also happens when object types are aliased...
export type Test = { prop: string; };
export type Test2 = { prop: number; };
export type AvatarSize = Test | Test2;
export type CardAvatarSize = Test | Test2;
...but not when they're inlined, which seems inconsistent?
export type AvatarSize = { prop: string; } | { prop: number; };
export type CardAvatarSize = { prop: string; } | { prop: number; };
Thanks!
The question in the title is the current behaviour.
TypeScript Version: 3.2.0-dev.20181027
Relates to: #25731
The compiler API will resolve some, but not all, equivalent types to the first encountered type:
I found #25731 that says this is a design limitation. What I was wondering is in the context of the compiler API, which people aren't using only for type checking, does it make sense to have this design? When working with the compiler api, I feel like it's valuable to have distinct
ts.Typeobjects whose text will be the name of the type alias used in the situation (ex. when someone doestype MyType = string;it would be nice for it to return aMyTypets.Typeobject instead of thestringone). Or does this just increase the complexity too much internally?Also note that this also happens when object types are aliased...
...but not when they're inlined, which seems inconsistent?
Thanks!