dsherret / ts-morph

TypeScript Compiler API wrapper for static analysis and programmatic code changes.
https://ts-morph.com
MIT License
4.94k stars 195 forks source link

How to create a `Type` instance #411

Closed rhys-vdw closed 3 years ago

rhys-vdw commented 6 years ago

Hey, had a poke around in the source and couldn't work out how to do this. (Nor could I work out how to make the typescript Node class.)

This is what I'm trying to achieve:

function getConditions(varName: string, types: ReadonlyArray<Type>): string {
  // Processes an array of types and turns them into code.
}

function getPropertyTypes(type: type, isOptional: boolean): Type[] {
                                      // vvvv This bit! vvvv
  const types: Type[] = isOptional ? [getTheUndefinedTypeInstanceSomehow()] : []
  if (type.isUnion()) {
    types.push(...type.getUnionTypes())
  } else {
    types.push(type)
  }
  return uniq(type)
}

function getPropertyConditions(varName: string, property: PropertySignature): string {
  const types = getPropertyTypes(property.getType(), property.hasQuestionToken())
  const propertyName = `${varName}.${property.getName()}`
  return getConditions(propertyName, types)
}

I need to create a Type instance for the undefined instance. Am I going about this the right way? Is it possible? My best guess so far is to actually create a new source file with an undefined export and get its type.

dsherret commented 6 years ago

Hey @rhys-vdw, when using the strictNullChecks compiler option, the type will include the undefined type:

const willHaveUndefined = true;

const project = new Project({ compilerOptions: { strictNullChecks: willHaveUndefined }});
const sourceFile = project.createSourceFile("test.ts", "class C { prop?: string; }");
const type = sourceFile.getClassOrThrow("C").getPropertyOrThrow("prop").getType();

expect(type.isNullable()).to.equal(willHaveUndefined);
expect(type.getUnionTypes().some(t => t.isUndefined())).to.equal(willHaveUndefined);

There's no way to create types/nodes except from what's provided to you from the library (see #376). I recommend creating your own abstraction of a type and using an undefined version of that.

rhys-vdw commented 6 years ago

Great, thanks for answering the question and also showing me that I didn't need to ask it. ;)