1

Im not quite sure what is going on here but I can't access an interface that seems to be exported from the TSServer protocol (https://github.com/Microsoft/TypeScript/blob/master/src/server/protocol.ts)

To take a step back, I am working on a project where the code does this...

if (renameResults) {
  if (renameResults.info.canRename) {
    // do stuff ... no errors
  }
} else {
  this.printErr(renameResults.info.localizedErrorMessage);
}

If you look at the TSServer protocol for the type you will see that this is a union type of RenameInfoSuccess | RenameInfoFailure here

the code above gives me the error Property 'localizedErrorMessage' does not exist on type 'RenameInfo'. Property 'localizedErrorMessage' does not exist on type 'RenameInfoSuccess'

but it cannot be RenameInfoSuccess because I had already checked for it to be false, right? I have tried every combination I could think of checking the attributes of info but nothing has worked. I thought I would try to get at the interface and use as or instanceof but I cannot seem to import the interface any way either....

How can I make the compiler happy here?

EDIT: added another line that made the typecheck more precise

1 Answer 1

2

Although if (renameResults) { checks for truthy/falsey, it won't narrow your specific union type. It would narrow a union of ... | null to remove the null.

You will need to write a custom type guard to narrow the union type.

For example:

function isRenameSuccess(obj: RenameInfoSuccess | RenameInfoFailure) : obj is RenameInfoSuccess {
    return obj.canRename;
}

This will narrow the type to RenameInfoSuccess in the if and RenameInfoFailure in the else when used like this:

if (isRenameSuccess(renameResults)) {
    // renameResults: RenameInfoSuccess
} else {
    // renameResults: RenameInfoFailure
}

You could also go the whole hog and turn those two types into a Discriminated Union type, which it very nearly is.

Sign up to request clarification or add additional context in comments.

3 Comments

Two things... 1. I made a mistake in my post and the typecheck that is already present is more precise (see the edited post). 2. I wanted to do exactly what you said, but I can't figure out how to import the types from the 'typescript/lib/protocol', they seem to be hidden or internal or something
scratch that last comment, it is working. IDK what happened before but it was telling me the interface type didn't exist. Thanks
No problem: 1. The check you are using isn't a type check, it checks the value. If you were using a discriminated union, it would work as you expect (i.e. the compiler would know that the property you are using is the discriminator). 2. You can set the library items you want using your tsconfig file in the lib option: typescriptlang.org/docs/handbook/compiler-options.html

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.