-
Notifications
You must be signed in to change notification settings - Fork 12.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add type relationship functions to checker public api #9943
Changes from 4 commits
dc8cf0d
ee18f7d
8e74ac8
fb946ad
e84db19
04e27cc
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -233,6 +233,60 @@ namespace ts { | |
return resolveName(location, escapeLeadingUnderscores(name), meaning, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined); | ||
}, | ||
getJsxNamespace: () => unescapeLeadingUnderscores(getJsxNamespace()), | ||
|
||
isIdenticalTo: (a, b) => checkTypeRelatedTo(a, b, identityRelation, /*errorNode*/ undefined), | ||
isSubtypeOf: (a, b) => checkTypeRelatedTo(a, b, subtypeRelation, /*errorNode*/ undefined), | ||
isAssignableTo: (a, b) => checkTypeRelatedTo(a, b, assignableRelation, /*errorNode*/ undefined), | ||
isComparableTo: areTypesComparable, | ||
isInstantiationOf: (a, b) => { | ||
return a && b && (a.target === b); | ||
}, | ||
|
||
lookupGlobalType: name => { | ||
const symbol = getSymbol(globals, escapeLeadingUnderscores(name), SymbolFlags.Type); | ||
return symbol ? getDeclaredTypeOfSymbol(symbol) : unknownType; | ||
}, | ||
lookupGlobalValueType: name => { | ||
const symbol = getSymbol(globals, escapeLeadingUnderscores(name), SymbolFlags.Value); | ||
return symbol ? getTypeOfSymbol(symbol) : unknownType; | ||
}, | ||
lookupTypeAt: (name, node) => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. wounder if we should just expose resolveName instead.. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Exposing it directly would make public way too many of the internal details, like usage checking, that are built into it. It's very overloaded, and the public API edition of its functionality should be simplified, I think. Looking at this again, I think There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should use |
||
const symbol = resolveName(node, escapeLeadingUnderscores(name), SymbolFlags.Type, /*nameNotFoundMessage*/undefined, /*nameArg*/undefined); | ||
return symbol ? getDeclaredTypeOfSymbol(symbol) : unknownType; | ||
}, | ||
lookupValueTypeAt: (name, node) => { | ||
const symbol = resolveName(node, escapeLeadingUnderscores(name), SymbolFlags.Value, /*nameNotFoundMessage*/undefined, /*nameArg*/undefined); | ||
return symbol ? getTypeOfSymbol(symbol) : unknownType; | ||
}, | ||
getTypeOfSymbol, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. do we need There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Possibly. We'd need to publish some good docs on what's a declared type vs a normal type and how a symbol can have both. |
||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. no need for this one i would say. |
||
getAnyType: () => anyType, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. should have a new function getBuiltinType instead of all of these.. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. or just |
||
getStringType: () => stringType, | ||
getNumberType: () => numberType, | ||
getBooleanType: () => booleanType, | ||
getVoidType: () => voidType, | ||
getUndefinedType: () => undefinedType, | ||
getNullType: () => nullType, | ||
getESSymbolType: () => esSymbolType, | ||
getNeverType: () => neverType, | ||
getUnknownType: () => unknownType, | ||
getStringLiteralType: (text: string) => { | ||
/* tslint:disable:no-null-keyword */ | ||
Debug.assert(text !== undefined && text !== null, "Argument to getStringLiteralType was null or undefined"); | ||
/* tslint:enable:no-null-keyword */ | ||
Debug.assert(typeof text === "string", "Argument to getStringLiteralType not a string"); | ||
return getLiteralType(text); | ||
}, | ||
getNumberLiteralType: (number: number) => { | ||
/* tslint:disable:no-null-keyword */ | ||
Debug.assert(number !== undefined && number !== null, "Argument to getNumberLiteralType was null or undefined"); | ||
/* tslint:enable:no-null-keyword */ | ||
Debug.assert(typeof number === "number", "Argument to getStringLiteralType not a number"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. consider merging these two into one getLiteralType |
||
return getLiteralType(number); | ||
}, | ||
getFalseType: () => falseType, | ||
getTrueType: () => trueType, | ||
getNonPrimitiveType: () => nonPrimitiveType, | ||
}; | ||
|
||
const tupleTypes: GenericType[] = []; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2686,8 +2686,104 @@ namespace ts { | |
|
||
/* @internal */ tryFindAmbientModuleWithoutAugmentations(moduleName: string): Symbol | undefined; | ||
|
||
|
||
/* @internal */ getSymbolWalker(accept?: (symbol: Symbol) => boolean): SymbolWalker; | ||
|
||
/** | ||
* Two types are considered identical when | ||
* - they are both the `any` type, | ||
* - they are the same primitive type, | ||
* - they are the same type parameter, | ||
* - they are union types with identical sets of constituent types, or | ||
* - they are intersection types with identical sets of constituent types, or | ||
* - they are object types with identical sets of members. | ||
* | ||
* This relationship is bidirectional. | ||
* See [here](https://github.com/Microsoft/TypeScript/blob/master/doc/spec.md#3.11.2) for more information. | ||
*/ | ||
isIdenticalTo(a: Type, b: Type): boolean; | ||
/** | ||
* `a` is a ___subtype___ of `b` (and `b` is a ___supertype___ of `a`) if `a` has no excess properties with respect to `b`, | ||
* and one of the following is true: | ||
* - `a` and `b` are identical types. | ||
* - `b` is the `any` type. | ||
* - `a` is the `undefined` type. | ||
* - `a` is the `null` type and `b` is _not_ the `undefined` type. | ||
* - `a` is an enum type and `b` is the primitive type `number`. | ||
* - `a` is a string literal type and `b` is the primitive type `string`. | ||
* - `a` is a union type and each constituient type of `b` is a subtype of `b`. | ||
* - `a` is an intersection type and at least one constituent type of `a` is a subtype of `b`. | ||
* - `b` is a union type and `a` is a subtype of at least one constituent type of `b`. | ||
* - `b` is an intersection type and `a` is a subtype of each constituent type of `b`. | ||
* - `a` is a type parameter and the constraint of `a` is a subtype of `b`. | ||
* - `a` has a subset of the structural members of `b`. | ||
* | ||
* This relationship is directional. | ||
* See [here](https://github.com/Microsoft/TypeScript/blob/master/doc/spec.md#3.11.3) for more information. | ||
*/ | ||
isSubtypeOf(a: Type, b: Type): boolean; | ||
/** | ||
* The assignable relationship differs only from the subtype relationship in that: | ||
* - the `any` type is assignable to, but not a subtype of, all types | ||
* - the primitive type `number` is assignable to, but not a subtype of, all enum types, and | ||
* - an object type without a particular property is assignable to an object type in which that property is optional. | ||
* | ||
* This relationship is directional. | ||
* See [here](https://github.com/Microsoft/TypeScript/blob/master/doc/spec.md#3.11.4) for more information. | ||
*/ | ||
isAssignableTo(a: Type, b: Type): boolean; | ||
/** | ||
* True if `a` is assignable to `b`, or `b` is assignable to `a`. Additionally, all unions with | ||
* overlapping constituient types are comparable, and unit types in the same domain are comparable. | ||
* This relationship is bidirectional. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This relationship is not bidirectional; at least not right now. You probably wanted to use It still feels strange that the other two are unidirectional but not this one. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Bidirectionality falls out of reflexivity in the identical relationship. Unidirectional comparability is more like a possibly-satisfies relationship, and if one type satisfies another in either direction, we consider those types comparable. I don't know if there is a good use case outside of comparison. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
*/ | ||
isComparableTo(a: Type, b: Type): boolean; | ||
/** | ||
* Not a formal relationship - returns true if a is an instantiation of the generic type b | ||
*/ | ||
isInstantiationOf(a: GenericType, b: GenericType): boolean; | ||
|
||
/** | ||
* Returns the declared type of the globally named symbol with meaning SymbolFlags.Type | ||
* Returns the unknown type on failure. | ||
*/ | ||
lookupGlobalType(name: string): Type; | ||
/** | ||
* Returns the declared type of the globally named symbol with meaning SymbolFlags.Value | ||
* Returns the unknown type on failure. | ||
*/ | ||
lookupGlobalValueType(name: string): Type; | ||
/** | ||
* Returns the declared type of the named symbol lexically at the position specified with meaning SymbolFlags.Type | ||
* Returns the unknown type on failure. | ||
*/ | ||
lookupTypeAt(name: string, position: Node): Type; | ||
/** | ||
* Returns the declared type of the named symbol lexically at the position specified with meaning SymbolFlags.Value | ||
* Returns the unknown type on failure. | ||
*/ | ||
lookupValueTypeAt(name: string, position: Node): Type; | ||
/** | ||
* Returns the type of a symbol | ||
*/ | ||
getTypeOfSymbol(symbol: Symbol): Type; | ||
|
||
getAnyType(): Type; | ||
getStringType(): Type; | ||
getNumberType(): Type; | ||
getBooleanType(): Type; | ||
getVoidType(): Type; | ||
getUndefinedType(): Type; | ||
getNullType(): Type; | ||
getESSymbolType(): Type; | ||
getNeverType(): Type; | ||
getUnknownType(): Type; | ||
getStringLiteralType(text: string): LiteralType; | ||
getNumberLiteralType(num: number): LiteralType; | ||
getFalseType(): Type; | ||
getTrueType(): Type; | ||
getNonPrimitiveType(): Type; | ||
|
||
// Should not be called directly. Should only be accessed through the Program instance. | ||
/* @internal */ getDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): Diagnostic[]; | ||
/* @internal */ getGlobalDiagnostics(): Diagnostic[]; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not sure we should include these..
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"These" meaning the global variant of the lookup functions? They're primarily convenience, so you don't have to provide the Lib's source file as the location as lookups for globals to the location-specific ones. (And looking at intent, many lint rules wanted to do thing like lookup the global promise or the global array or symbol)