Struct stc_ts_file_analyzer::analyzer::WithCtx
source · [−]Fields
analyzer: &'a mut Analyzer<'b, 'c>
orig_ctx: Ctx
Methods from Deref<Target = Analyzer<'b, 'c>>
sourcepub(super) fn assign_to_builtin(
&mut self,
data: &mut AssignData,
l: &Type,
r: &Type,
opts: AssignOpts
) -> Option<VResult<()>>
pub(super) fn assign_to_builtin(
&mut self,
data: &mut AssignData,
l: &Type,
r: &Type,
opts: AssignOpts
) -> Option<VResult<()>>
This handles the assignment to builtin types.
- Handles assignment of
Function
types. - Handles assignment of various array types.
- Handles assignment of promise types.
sourcepub(crate) fn can_be_casted_to_number_in_rhs(
&mut self,
span: Span,
ty: &Type
) -> bool
pub(crate) fn can_be_casted_to_number_in_rhs(
&mut self,
span: Span,
ty: &Type
) -> bool
Returns true if the type can be casted to number if it’s in the rvalue position.
pub(super) fn assign_to_class_def(
&mut self,
data: &mut AssignData,
l: &ClassDef,
r: &Type,
opts: AssignOpts
) -> VResult<()>
pub(super) fn assign_to_class(
&mut self,
data: &mut AssignData,
l: &Class,
r: &Type,
opts: AssignOpts
) -> VResult<()>
fn assign_class_members_to_class_member(
&mut self,
data: &mut AssignData,
l: &ClassMember,
r: &[ClassMember],
opts: AssignOpts
) -> VResult<()>
pub(crate) fn assign_to_fn_like(
&mut self,
data: &mut AssignData,
is_call: bool,
l_type_params: Option<&TypeParamDecl>,
l_params: &[FnParam],
l_ret_ty: Option<&Type>,
r_type_params: Option<&TypeParamDecl>,
r_params: &[FnParam],
r_ret_ty: Option<&Type>,
opts: AssignOpts
) -> VResult<()>
sourcepub(super) fn assign_to_function(
&mut self,
data: &mut AssignData,
lt: &Type,
l: &Function,
r: &Type,
opts: AssignOpts
) -> VResult<()>
pub(super) fn assign_to_function(
&mut self,
data: &mut AssignData,
lt: &Type,
l: &Function,
r: &Type,
opts: AssignOpts
) -> VResult<()>
class Base {}
class Derived extends Base {
}
declare var a: (b: Base) => {};
declare var b: (b: Derived) => { foo: string };
a = b;
b = a; // error
sourcepub(super) fn assign_to_constructor(
&mut self,
data: &mut AssignData,
lt: &Type,
l: &Constructor,
r: &Type,
opts: AssignOpts
) -> VResult<()>
pub(super) fn assign_to_constructor(
&mut self,
data: &mut AssignData,
lt: &Type,
l: &Constructor,
r: &Type,
opts: AssignOpts
) -> VResult<()>
Note
We should distinguish assign failure due to type parameter instantiation with assign failure due to type element kind mismatch.
declare var a16: {
new (x: {
new (a: number): number;
new (a?: number): number;
}): number[];
new (x: {
new (a: boolean): boolean;
new (a?: boolean): boolean;
}): boolean[];
};
declare var b16: new <T>(x: (a: T) => T) => T[];
a16 = b16; // error
b16 = a16; // error
declare var a18: {
new (x: {
(a: number): number;
(a: string): string;
}): any[];
new (x: {
(a: boolean): boolean;
(a: Date): Date;
}): any[];
}
declare var b18: new <T>(x: (a: T) => T) => T[];
a18 = b18; // ok
b18 = a18; // ok
sourcefn assign_param(
&mut self,
data: &mut AssignData,
l: &FnParam,
r: &FnParam,
opts: AssignOpts
) -> VResult<()>
fn assign_param(
&mut self,
data: &mut AssignData,
l: &FnParam,
r: &FnParam,
opts: AssignOpts
) -> VResult<()>
Assigns a parameter to another one. It may assign in reverse direction because of the rule 1. At the same time, it should not be reversed in some cases. (See rule 2)
Rule 1
declare let a: (parent: 'foo' | 'bar') => void
declare let b: (parent: 'bar') => void
a = b // error
b = a // ok
Valid assignment is foo | bar
= bar
, which is a.param[0] = b.param[0]
, but it doesn’t match b = a
.
Rule 2
class Base {
private foo!: string
}
class Derived extends Base {
private bar!: string
}
declare var a: (y: Derived) => any;
declare var b: (y: Base) => any
a = b // ok
b = a // error
Valid assignment is Derived = Base
, which is a.params[0] = b.param[0]
and it matches a = b
.
Notes
string
is assignable to...args: any[]
.
sourcefn assign_param_type(
&mut self,
data: &mut AssignData,
l: &Type,
r: &Type,
opts: AssignOpts
) -> VResult<()>
fn assign_param_type(
&mut self,
data: &mut AssignData,
l: &Type,
r: &Type,
opts: AssignOpts
) -> VResult<()>
Implementation of assign_param
.
sourcepub(crate) fn assign_params(
&mut self,
data: &mut AssignData,
l: &[FnParam],
r: &[FnParam],
opts: AssignOpts
) -> VResult<()>
pub(crate) fn assign_params(
&mut self,
data: &mut AssignData,
l: &[FnParam],
r: &[FnParam],
opts: AssignOpts
) -> VResult<()>
Validation of parameter count
A parameter named this
is excluded.
Rule
declare var a: (x: string) => any;
declare var b: (x: string, y: number) => any
a = b // error
b = a // ok
So, it’s an error if l.params.len() < r.params.len()
.
sourcepub(crate) fn assign_to_tpl(
&mut self,
data: &mut AssignData,
l: &TplType,
r_ty: &Type,
opts: AssignOpts
) -> VResult<()>
pub(crate) fn assign_to_tpl(
&mut self,
data: &mut AssignData,
l: &TplType,
r_ty: &Type,
opts: AssignOpts
) -> VResult<()>
Implementation notes
We split string based on the literals.
:${string}:::${string}:
= “:1:sss:s:s:s:s::s:s:”
For the code above, we try to find :
, :::
, :
, while preserving
orders.
After splitting, we can check if each element is assignable.
sourcepub(crate) fn is_valid_type_for_tpl_lit_placeholder(
&mut self,
span: Span,
source: &Type,
target: &Type
) -> VResult<bool>
pub(crate) fn is_valid_type_for_tpl_lit_placeholder(
&mut self,
span: Span,
source: &Type,
target: &Type
) -> VResult<bool>
Ported from isValidTypeForTemplateLiteralPlaceholder
of tsc
Ported from templateLiteralTypesDefinitelyUnrelated
of tsc
.
sourcepub(crate) fn assign_to_type_elements(
&mut self,
data: &mut AssignData,
lhs_span: Span,
lhs: &[TypeElement],
rhs: &Type,
lhs_metadata: TypeLitMetadata,
opts: AssignOpts
) -> VResult<()>
pub(crate) fn assign_to_type_elements(
&mut self,
data: &mut AssignData,
lhs_span: Span,
lhs: &[TypeElement],
rhs: &Type,
lhs_metadata: TypeLitMetadata,
opts: AssignOpts
) -> VResult<()>
This method is called when lhs of assignment is interface or type literal.
interface A {}
let a: A = foo;
let b: { key: string } = foo;
fn should_report_properties(
&mut self,
span: Span,
lhs: &[TypeElement],
rhs: &Type
) -> bool
pub(super) fn try_assign_using_parent(
&mut self,
data: &mut AssignData,
l: &Type,
r: &Type,
opts: AssignOpts
) -> Option<VResult<()>>
fn handle_assignment_of_type_elements_to_type_elements(
&mut self,
data: &mut AssignData,
missing_fields: &mut Vec<TypeElement>,
unhandled_rhs: &mut Vec<Span>,
lhs: &[TypeElement],
lhs_metadata: TypeLitMetadata,
rhs: &[TypeElement],
opts: AssignOpts
) -> VResult<()>
sourcefn assign_type_elements_to_type_element(
&mut self,
data: &mut AssignData,
missing_fields: &mut Vec<TypeElement>,
unhandled_rhs: &mut Vec<Span>,
lms: &[&TypeElement],
lhs_metadata: TypeLitMetadata,
rhs_members: &[TypeElement],
opts: AssignOpts
) -> VResult<()>
fn assign_type_elements_to_type_element(
&mut self,
data: &mut AssignData,
missing_fields: &mut Vec<TypeElement>,
unhandled_rhs: &mut Vec<Span>,
lms: &[&TypeElement],
lhs_metadata: TypeLitMetadata,
rhs_members: &[TypeElement],
opts: AssignOpts
) -> VResult<()>
This method assigns each property to corresponding property.
Because of overloads, this methods takes &[TypeElement]
instead of
TypeElement for lhs.
Implementation notes
Methods
Type parameters
interface T {
f(x: number): void;
}
var t: T;
t = { f: <T>(x:T) => 1 };
This is valid.
Call signatures
(s: string): void
(s: number): void
}
declare var b: {
(s: string): void
}
a = b // error
b = a // ok
sourcepub(super) fn assign_to_union(
&mut self,
data: &mut AssignData,
l: &Type,
r: &Type,
opts: AssignOpts
) -> Option<VResult<()>>
pub(super) fn assign_to_union(
&mut self,
data: &mut AssignData,
l: &Type,
r: &Type,
opts: AssignOpts
) -> Option<VResult<()>>
Cases
Cases handled by this methods are
- lhs =
(["a", number] | ["b", number] | ["c", string]);
- rhs =
[("b" | "a"), 1];
fn flatten_unions_for_assignment(
&mut self,
span: Span,
ty: Cow<'_, Type>
) -> VResult<Type>
sourcefn append_type_element_to_type(
&mut self,
span: Span,
to: &mut Type,
el: &TypeElement
) -> VResult<()>
fn append_type_element_to_type(
&mut self,
span: Span,
to: &mut Type,
el: &TypeElement
) -> VResult<()>
TODO(kdy1): Use Cow
sourcefn append_tuple_element_to_type(
&mut self,
span: Span,
to: &mut Type,
el: &TupleElement
) -> VResult<()>
fn append_tuple_element_to_type(
&mut self,
span: Span,
to: &mut Type,
el: &TupleElement
) -> VResult<()>
TODO(kdy1): Use Cow
sourcepub(crate) fn deny_null_or_undefined(
&mut self,
span: Span,
ty: &Type
) -> VResult<()>
pub(crate) fn deny_null_or_undefined(
&mut self,
span: Span,
ty: &Type
) -> VResult<()>
Denies null
and undefined
. This method does not check for elements
of union.
sourcepub(crate) fn assign_with_operator(
&mut self,
span: Span,
op: AssignOp,
lhs: &Type,
rhs: &Type
) -> VResult<()>
pub(crate) fn assign_with_operator(
&mut self,
span: Span,
op: AssignOp,
lhs: &Type,
rhs: &Type
) -> VResult<()>
Used to validate assignments like a += b
.
sourcepub(crate) fn assign(
&mut self,
span: Span,
data: &mut AssignData,
left: &Type,
right: &Type
) -> VResult<()>
pub(crate) fn assign(
&mut self,
span: Span,
data: &mut AssignData,
left: &Type,
right: &Type
) -> VResult<()>
Assign right
to left
. You can just use default for AssignData.
sourcepub(crate) fn assign_with_opts(
&mut self,
data: &mut AssignData,
left: &Type,
right: &Type,
opts: AssignOpts
) -> VResult<()>
pub(crate) fn assign_with_opts(
&mut self,
data: &mut AssignData,
left: &Type,
right: &Type,
opts: AssignOpts
) -> VResult<()>
Assign right
to left
. You can just use default for AssignData.
fn normalize_for_assign<'a>(
&mut self,
span: Span,
ty: &'a Type,
opts: AssignOpts
) -> VResult<Cow<'a, Type>>
fn assign_inner(
&mut self,
data: &mut AssignData,
left: &Type,
right: &Type,
opts: AssignOpts
) -> VResult<()>
sourcefn assign_without_wrapping(
&mut self,
data: &mut AssignData,
to: &Type,
rhs: &Type,
opts: AssignOpts
) -> VResult<()>
fn assign_without_wrapping(
&mut self,
data: &mut AssignData,
to: &Type,
rhs: &Type,
opts: AssignOpts
) -> VResult<()>
Assigns, but does not wrap error with [Error::AssignFailed].
sourcefn assign_to_intrinsic(
&mut self,
data: &mut AssignData,
to: &StringMapping,
r: &Type,
opts: AssignOpts
) -> VResult<()>
fn assign_to_intrinsic(
&mut self,
data: &mut AssignData,
to: &StringMapping,
r: &Type,
opts: AssignOpts
) -> VResult<()>
Should be called only if to
is not expandable.
fn extract_keys(&mut self, span: Span, ty: &Type) -> VResult<Type>
sourcefn assign_keys(
&mut self,
data: &mut AssignData,
keys: &Type,
rhs: &Type,
opts: AssignOpts
) -> VResult<()>
fn assign_keys(
&mut self,
data: &mut AssignData,
keys: &Type,
rhs: &Type,
opts: AssignOpts
) -> VResult<()>
Handles P in 'foo' | 'bar'
. Note that 'foo' | 'bar'
part should be
passed as keys
.
Currently only literals and unions are supported for keys
.
fn assign_to_mapped(
&mut self,
data: &mut AssignData,
l: &Mapped,
r: &Type,
opts: AssignOpts
) -> VResult<()>
sourcefn should_use_special_union_assignment(
&mut self,
span: Span,
r: &Type
) -> VResult<bool>
fn should_use_special_union_assignment(
&mut self,
span: Span,
r: &Type
) -> VResult<bool>
Returns true for A | B | | C = A | B
and similar cases.
Should be called iff lhs is a union type.
sourcefn variance(&mut self, ty: &Conditional) -> VResult<Variance>
fn variance(&mut self, ty: &Conditional) -> VResult<Variance>
TODO(kdy1): I’m not sure about this.
fn is_covariant(&mut self, check_type: &Type, output_type: &Type) -> VResult<bool>
fn is_contravariant(
&mut self,
check_type: &Type,
output_type: &Type
) -> VResult<bool>
sourcepub(super) fn calc_eval_order_of_class_methods(
&mut self,
remaining_indexes: Vec<usize>,
members: &[RClassMember]
) -> Vec<usize>ⓘNotable traits for Vec<u8, A>impl<A> Write for Vec<u8, A>where
A: Allocator,
pub(super) fn calc_eval_order_of_class_methods(
&mut self,
remaining_indexes: Vec<usize>,
members: &[RClassMember]
) -> Vec<usize>ⓘNotable traits for Vec<u8, A>impl<A> Write for Vec<u8, A>where
A: Allocator,
A: Allocator,
Calculate the order of the evaluation of class members. This is used to avoid reevaluation if possible.
Note that this is not perfect, and if class methods references each
other, we have to evaluate them again with any
for references.
This method ignores order of class properties or parameter properties.
So the length of returned vector can be smaller than length of
members
.
Note that the body constructor is analyzed.
pub(crate) fn is_type_param_declared_in_containing_class(
&mut self,
id: &Id
) -> bool
fn validate_type_of_class_property(
&mut self,
span: Span,
readonly: bool,
is_static: bool,
type_ann: &Option<Box<RTsTypeAnn>>,
value: &Option<Box<RExpr>>
) -> VResult<Option<Type>>
fn report_errors_for_duplicate_class_members(
&mut self,
c: &RClass
) -> VResult<()>
fn report_errors_for_statics_mixed_with_instances(
&mut self,
c: &RClass
) -> VResult<()>
fn report_errors_for_wrong_ambient_methods_of_class(
&mut self,
c: &RClass,
declare: bool
) -> VResult<()>
pub(super) fn validate_computed_prop_key(
&mut self,
span: Span,
key: &RExpr
) -> VResult<()>
sourcefn report_errors_for_conflicting_interfaces(&mut self, interfaces: &[TsExpr])
fn report_errors_for_conflicting_interfaces(&mut self, interfaces: &[TsExpr])
TODO(kdy1): Implement this.
fn report_errors_for_wrong_implementations_of_class(
&mut self,
name: Option<Span>,
class: &ArcCow<ClassDef>
)
sourcefn validate_inherited_members_from_super_class(
&mut self,
name: Option<Span>,
class: &ClassDef
)
fn validate_inherited_members_from_super_class(
&mut self,
name: Option<Span>,
class: &ClassDef
)
Should be called only from Validate<Class>
.
fn report_error_for_wrong_super_class_inheritance(
&mut self,
span: Span,
members: &[ClassMember],
super_ty: &Type
)
sourcefn combine_class_properties(
&mut self,
body: Vec<(usize, ClassMember)>
) -> Vec<(usize, ClassMember)>ⓘNotable traits for Vec<u8, A>impl<A> Write for Vec<u8, A>where
A: Allocator,
fn combine_class_properties(
&mut self,
body: Vec<(usize, ClassMember)>
) -> Vec<(usize, ClassMember)>ⓘNotable traits for Vec<u8, A>impl<A> Write for Vec<u8, A>where
A: Allocator,
A: Allocator,
This method combines setters and getters, and merge it just like a normal property.
sourcefn report_errors_for_class_member_incompatible_with_index_signature(
&mut self,
class: &ClassDef
) -> VResult<()>
fn report_errors_for_class_member_incompatible_with_index_signature(
&mut self,
class: &ClassDef
) -> VResult<()>
If a class have an index signature, properties should be compatible with it.
fn report_errors_for_wrong_constructor_overloads(
&mut self,
ambient: &[ConstructorSignature],
cons_with_body: Option<&ConstructorSignature>
) -> VResult<()>
fn validate_super_class(&mut self, span: Span, ty: &Type)
sourcepub(crate) fn instantiate_class(&mut self, span: Span, ty: &Type) -> VResult<Type>
pub(crate) fn instantiate_class(&mut self, span: Span, ty: &Type) -> VResult<Type>
TODO(kdy1): Instantiate fully
fn visit_class_decl_inner(&mut self, c: &RClassDecl)
sourcefn adjust_ternary_type(
&mut self,
span: Span,
types: Vec<Type>
) -> VResult<Vec<Type>>
fn adjust_ternary_type(
&mut self,
span: Span,
types: Vec<Type>
) -> VResult<Vec<Type>>
This method may remove SafeSubscriber
from Subscriber
|
SafeSubscriber
or downgrade the type, like converting Subscriber
|
SafeSubscriber
into SafeSubscriber
. This behavior is controlled by
the mark applied while handling type facts related to call.
fn downcast_types(&mut self, span: Span, types: Vec<Type>) -> VResult<Vec<Type>>
sourcefn remove_child_types(
&mut self,
span: Span,
types: Vec<Type>
) -> VResult<Vec<Type>>
fn remove_child_types(
&mut self,
span: Span,
types: Vec<Type>
) -> VResult<Vec<Type>>
Remove SafeSubscriber
from Subscriber
| SafeSubscriber
.
sourcefn report_errors_for_incomparable_switch_cases(
&mut self,
s: &RSwitchStmt
) -> VResult<Type>
fn report_errors_for_incomparable_switch_cases(
&mut self,
s: &RSwitchStmt
) -> VResult<Type>
Returns the type of discriminant.
TODO(kdy1): Implement this.
sourcefn is_switch_case_body_unconditional_termination<S>(
&mut self,
body: &[S]
) -> boolwhere
S: Borrow<RStmt>,
fn is_switch_case_body_unconditional_termination<S>(
&mut self,
body: &[S]
) -> boolwhere
S: Borrow<RStmt>,
Returns true if a body of switch always ends with return
, throw
or
continue
.
TODO(kdy1): Support break with other label.
pub(super) fn try_assign(
&mut self,
span: Span,
op: AssignOp,
lhs: &RPatOrExpr,
rhs_ty: &Type
) -> Type
pub(super) fn try_assign_pat(
&mut self,
span: Span,
lhs: &RPat,
ty: &Type
) -> VResult<()>
fn try_assign_pat_with_opts(
&mut self,
span: Span,
lhs: &RPat,
ty: &Type,
opts: PatAssignOpts
) -> VResult<()>
sourcepub(super) fn add_type_fact(&mut self, sym: &Id, ty: Type, exclude: Type)
pub(super) fn add_type_fact(&mut self, sym: &Id, ty: Type, exclude: Type)
While this type fact is in scope, the var named sym
will be treated as
ty
.
pub(super) fn add_deep_type_fact(
&mut self,
span: Span,
name: Name,
ty: Type,
is_for_true: bool
)
sourcepub(super) fn narrow_types_with_property(
&mut self,
span: Span,
src: &Type,
property: &JsWord,
type_facts: Option<TypeFacts>
) -> VResult<Type>
pub(super) fn narrow_types_with_property(
&mut self,
span: Span,
src: &Type,
property: &JsWord,
type_facts: Option<TypeFacts>
) -> VResult<Type>
If type_facts
is None, this method calculates type facts created by
'foo' in obj
.
Otherwise, this method calculates type facts created by if (a.foo) ;
.
In this case, this method tests if type_facts
matches the type of
property and returns never
if it does not.
fn determine_type_fact_by_field_fact(
&mut self,
span: Span,
name: &Name,
ty: &Type
) -> VResult<Option<(Name, Type)>>
pub(super) fn report_error_for_wrong_interface_inheritance(
&mut self,
span: Span,
body: &[TypeElement],
parent: &[TsExpr]
)
pub(crate) fn report_error_for_conflicting_parents(
&mut self,
span: Span,
parent: &[TsExpr]
)
fn report_error_for_duplicate_type_elements(&mut self, elems: &[TypeElement])
fn report_error_for_duplicate_params(&mut self, params: &[FnParam])
fn report_error_for_type_param_usages_in_static_members(&mut self, i: &RIdent)
sourcepub(crate) fn default_any_pat(&mut self, p: &RPat)
pub(crate) fn default_any_pat(&mut self, p: &RPat)
Handle implicit defaults.
sourcepub(crate) fn default_any_ident(&mut self, i: &RBindingIdent)
pub(crate) fn default_any_ident(&mut self, i: &RBindingIdent)
Handle implicit defaults.
sourcepub(crate) fn default_any_array_pat(&mut self, arr: &RArrayPat)
pub(crate) fn default_any_array_pat(&mut self, arr: &RArrayPat)
Handle implicit defaults.
sourcepub(crate) fn default_any_object(&mut self, obj: &RObjectPat)
pub(crate) fn default_any_object(&mut self, obj: &RObjectPat)
Handle implicit defaults.
sourcepub(crate) fn default_any_param(&mut self, p: &RTsFnParam)
pub(crate) fn default_any_param(&mut self, p: &RTsFnParam)
Handle implicit defaults.
fn type_element_to_class_member(
&mut self,
el: &TypeElement
) -> VResult<Option<ClassMember>>
sourcefn merge_from_to(&mut self, span: Span, a: Type, b: Type) -> VResult<Option<Type>>
fn merge_from_to(&mut self, span: Span, a: Type, b: Type) -> VResult<Option<Type>>
Handle declaration merging. This method is used to avoid implementing same logic twice.
sourcefn merge_declaration_types(
&mut self,
span: Span,
orig: Type,
new: Type
) -> VResult<Type>
fn merge_declaration_types(
&mut self,
span: Span,
orig: Type,
new: Type
) -> VResult<Type>
Handle declaration merging.
pub(crate) fn merge_decl_with_name(
&mut self,
name: Id,
new: Type
) -> VResult<(Type, bool)>
fn validate_enum_member_name(&mut self, e: &RTsEnumMemberId) -> VResult<()>
sourcepub(super) fn enum_to_type_lit(&mut self, e: &ArcCow<Enum>) -> VResult<TypeLit>
pub(super) fn enum_to_type_lit(&mut self, e: &ArcCow<Enum>) -> VResult<TypeLit>
enumBasics.ts
says
Enum object type is anonymous with properties of the enum type and numeric indexer.
and following is valid.
var e = E1;
var e: {
readonly A: E1.A;
readonly B: E1.B;
readonly C: E1.C;
readonly [n: number]: string;
};
var e: typeof E1;
pub(super) fn report_error_for_invalid_rvalue(
&mut self,
span: Span,
lhs: &RPat,
rhs_ty: &Type
)
fn validate_member_of_str_enum(&mut self, m: &RTsEnumMember)
sourcepub(super) fn expand_enum(&self, ty: Type) -> VResult<Type>
pub(super) fn expand_enum(&self, ty: Type) -> VResult<Type>
Converts e
in o[e]
from the code below to 'a' | 'b'
enum E {
A = 'a',
B = 'b',
}
const o = { a: 1, b: 2 };
declare const e: E;
const a = o[e]
sourcepub(super) fn expand_enum_variant(&self, ty: Type) -> VResult<Type>
pub(super) fn expand_enum_variant(&self, ty: Type) -> VResult<Type>
Expands an enum variant as a literal.
sourcefn report_errors_for_duplicated_exports_of_var(&mut self, span: Span, sym: JsWord)
fn report_errors_for_duplicated_exports_of_var(&mut self, span: Span, sym: JsWord)
Currently noop because we need to know if a function is last item among overloads
fn export_var(
&mut self,
span: Span,
name: Id,
orig_name: Option<Id>,
check_duplicate: bool
)
fn export_named(&mut self, span: Span, ctxt: ModuleId, orig: Id, id: Id)
fn reexport(&mut self, span: Span, ctxt: ModuleId, from: ModuleId, orig: Id, id: Id)
sourcepub(crate) fn get_element_from_iterator<'a>(
&mut self,
span: Span,
iterator: Cow<'a, Type>,
n: usize
) -> VResult<Cow<'a, Type>>
pub(crate) fn get_element_from_iterator<'a>(
&mut self,
span: Span,
iterator: Cow<'a, Type>,
n: usize
) -> VResult<Cow<'a, Type>>
Get n
th element from the iterator
.
pub(crate) fn get_async_iterator_element_type<'a>(
&mut self,
span: Span,
ty: Cow<'a, Type>
) -> VResult<Cow<'a, Type>>
pub(crate) fn get_value_type_from_iterator_result<'a>(
&mut self,
span: Span,
iterator_result: Cow<'a, Type>
) -> VResult<Cow<'a, Type>>
pub(crate) fn get_rest_elements<'a>(
&mut self,
span: Option<Span>,
iterator: Cow<'a, Type>,
start_index: usize
) -> VResult<Cow<'a, Type>>
pub(crate) fn get_iterator<'a>(
&mut self,
span: Span,
ty: Cow<'a, Type>,
opts: GetIteratorOpts
) -> VResult<Cow<'a, Type>>
fn get_iterator_inner<'a>(
&mut self,
span: Span,
ty: Cow<'a, Type>,
opts: GetIteratorOpts
) -> VResult<Cow<'a, Type>>
sourcepub(crate) fn get_iterator_element_type<'a>(
&mut self,
span: Span,
ty: Cow<'a, Type>,
try_next_value: bool,
opts: GetIteratorOpts
) -> VResult<Cow<'a, Type>>
pub(crate) fn get_iterator_element_type<'a>(
&mut self,
span: Span,
ty: Cow<'a, Type>,
try_next_value: bool,
opts: GetIteratorOpts
) -> VResult<Cow<'a, Type>>
sourcefn get_next_value_type_of_iterator(
&mut self,
span: Span,
iterator: Cow<'_, Type>
) -> VResult<Type>
fn get_next_value_type_of_iterator(
&mut self,
span: Span,
iterator: Cow<'_, Type>
) -> VResult<Type>
Returns the type of iterator.next().value
.
pub(crate) fn calculate_tuple_element_count(
&mut self,
span: Span,
ty: &Type
) -> VResult<Option<usize>>
pub(crate) fn get_awaited_type<'a>(
&mut self,
span: Span,
ty: Cow<'a, Type>,
error_on_missing_then: bool
) -> VResult<Cow<'a, Type>>
fn validate_bin_expr(
&mut self,
e: &RBinExpr,
type_ann: Option<&Type>
) -> VResult<Type>
fn add_type_facts_for_typeof(
&mut self,
span: Span,
l: &RExpr,
r: &RExpr,
is_eq: bool,
l_ty: &Type,
r_ty: &Type
) -> VResult<()>
sourcefn add_type_facts_for_opt_chains(
&mut self,
span: Span,
l: &RExpr,
r: &RExpr,
lt: &Type,
rt: &Type
) -> VResult<()>
fn add_type_facts_for_opt_chains(
&mut self,
span: Span,
l: &RExpr,
r: &RExpr,
lt: &Type,
rt: &Type
) -> VResult<()>
Example
// Note: feature.geometry can be undefined
function extractCoordinates(f: Feature): number[] {
if (f.geometry?.type !== 'test') {
return [];
}
return f.geometry.coordinates;
}
The condition in the if statement above will be true
if f.geometry
is undefined
.
fn can_compare_with_eq(
&mut self,
span: Span,
disc_ty: &Type,
case_ty: &Type
) -> VResult<bool>
sourcefn narrow_with_instanceof(
&mut self,
span: Span,
ty: Cow<'_, Type>,
orig_ty: &Type
) -> VResult<Type>
fn narrow_with_instanceof(
&mut self,
span: Span,
ty: Cow<'_, Type>,
orig_ty: &Type
) -> VResult<Type>
We have to check for inheritance.
class C1 {
p1: string;
}
class C2 {
p2: number;
}
class D1 extends C1 {
p3: number;
}
var ctor2: C2 | D1;
var r2: D1 | C2 = ctor2 instanceof C1 && ctor2; // C2 | D1
in this case, we cannot store ctor2 as C1 because it would result in an error.
TODO(kdy1): Use Cow
Related tests
narrowingConstrainedTypeVariable.ts
In the test, there’s function f2<T extends C, U extends D>(v: T | U) {}
.
If we apply instanceof C
to v
, v
becomes T
.
Note that C extends D
and D extends C
are true because both of C
and D
are empty classes.
fn validate_relative_comparison_operands(
&mut self,
span: Span,
op: BinaryOp,
l: &Type,
r: &Type
) -> VResult<()>
fn verify_rel_cmp_operands(
&mut self,
span: Span,
op: BinaryOp,
l: &Type,
r: &Type
) -> VResult<()>
sourcefn can_compare_type_elements_relatively(
&mut self,
span: Span,
l: &[TypeElement],
r: &[TypeElement]
) -> VResult<Option<bool>>
fn can_compare_type_elements_relatively(
&mut self,
span: Span,
l: &[TypeElement],
r: &[TypeElement]
) -> VResult<Option<bool>>
Returns Ok(Some(v)) if this method has a special rule to handle type elements.
fn is_valid_lhs_of_instanceof(&mut self, span: Span, ty: &Type) -> bool
sourcefn validate_rhs_of_instanceof(
&mut self,
span: Span,
type_for_error: &Type,
ty: Type
) -> Type
fn validate_rhs_of_instanceof(
&mut self,
span: Span,
type_for_error: &Type,
ty: Type
) -> Type
The right operand to be of type Any or a subtype of the ‘Function’ interface type.
sourcefn calc_type_facts_for_equality(
&mut self,
name: Name,
equals_to: &Type
) -> VResult<(Name, Type, Vec<Type>)>
fn calc_type_facts_for_equality(
&mut self,
name: Name,
equals_to: &Type
) -> VResult<(Name, Type, Vec<Type>)>
We should create a type fact for foo
in if (foo.type === 'bar');
.
Returns (name, true_fact, false_fact)
.
sourcefn narrow_with_equality(
&mut self,
orig_ty: &Type,
equals_to: &Type
) -> VResult<Type>
fn narrow_with_equality(
&mut self,
orig_ty: &Type,
equals_to: &Type
) -> VResult<Type>
Returns new type of the variable after comparison with ===
.
Parameters
orig_ty
Original type of the variable.
fn report_errors_for_bin_expr(
&mut self,
span: Span,
op: BinaryOp,
lt: &Type,
rt: &Type
)
fn is_valid_lhs_of_in(&mut self, ty: &Type) -> bool
fn is_valid_rhs_of_in(&mut self, span: Span, ty: &Type) -> bool
fn report_errors_for_mixed_nullish_coalescing(&mut self, e: &RBinExpr)
fn get_additional_exclude_target(
&mut self,
span: Span,
origin_ty: Type,
r: &Type,
name: Name,
is_loose_comparison: bool
) -> FxHashMap<Name, Vec<Type>>
fn get_additional_exclude_target_for_type_lit(
&mut self,
span: Span,
origin_ty: &Type,
tl: &TypeLit,
r: &Type,
name: Name,
additional_target: &mut FxHashMap<Name, Vec<Type>>,
is_loose_comparison: bool
)
sourcefn extract_call_new_expr_member(
&mut self,
span: Span,
expr: ReEvalMode<'_>,
callee: &RExpr,
kind: ExtractKind,
args: &[RExprOrSpread],
type_args: Option<&RTsTypeParamInstantiation>,
type_ann: Option<&Type>
) -> VResult<Type>
fn extract_call_new_expr_member(
&mut self,
span: Span,
expr: ReEvalMode<'_>,
callee: &RExpr,
kind: ExtractKind,
args: &[RExprOrSpread],
type_args: Option<&RTsTypeParamInstantiation>,
type_ann: Option<&Type>
) -> VResult<Type>
Calculates the return type of a new /call expression.
This method check arguments
sourcepub(super) fn call_property(
&mut self,
span: Span,
kind: ExtractKind,
expr: ReEvalMode<'_>,
this: &Type,
obj_type: &Type,
prop: &Key,
type_args: Option<&TypeParamInstantiation>,
args: &[RExprOrSpread],
arg_types: &[TypeOrSpread],
spread_arg_types: &[TypeOrSpread],
type_ann: Option<&Type>,
opts: CallOpts
) -> VResult<Type>
pub(super) fn call_property(
&mut self,
span: Span,
kind: ExtractKind,
expr: ReEvalMode<'_>,
this: &Type,
obj_type: &Type,
prop: &Key,
type_args: Option<&TypeParamInstantiation>,
args: &[RExprOrSpread],
arg_types: &[TypeOrSpread],
spread_arg_types: &[TypeOrSpread],
type_ann: Option<&Type>,
opts: CallOpts
) -> VResult<Type>
TODO(kdy1): Use Cow for obj_type
Parameters
expr
: Can be default if argument does not include an arrow expression nor a function expression.
fn extract_callable_properties_of_class(
&mut self,
span: Span,
kind: ExtractKind,
c: &ClassDef,
prop: &Key,
is_static_call: bool
) -> VResult<Vec<CallCandidate>>
fn call_property_of_class(
&mut self,
span: Span,
expr: ReEvalMode<'_>,
kind: ExtractKind,
this: &Type,
c: &ClassDef,
prop: &Key,
is_static_call: bool,
type_args: Option<&TypeParamInstantiation>,
args: &[RExprOrSpread],
arg_types: &[TypeOrSpread],
spread_arg_types: &[TypeOrSpread],
type_ann: Option<&Type>,
opts: CallOpts
) -> VResult<Option<Type>>
fn check_type_element_for_call<'a>(
&mut self,
span: Span,
kind: ExtractKind,
candidates: &mut Vec<CallCandidate>,
m: &'a TypeElement,
prop: &Key,
opts: CallOpts
)
fn call_property_of_type_elements(
&mut self,
kind: ExtractKind,
expr: ReEvalMode<'_>,
span: Span,
obj: &Type,
members: &[TypeElement],
prop: &Key,
type_args: Option<&TypeParamInstantiation>,
args: &[RExprOrSpread],
arg_types: &[TypeOrSpread],
spread_arg_types: &[TypeOrSpread],
type_ann: Option<&Type>,
opts: CallOpts
) -> VResult<Type>
sourcefn spread_args<'a>(
&mut self,
arg_types: &'a [TypeOrSpread]
) -> VResult<Cow<'a, [TypeOrSpread]>>
fn spread_args<'a>(
&mut self,
arg_types: &'a [TypeOrSpread]
) -> VResult<Cow<'a, [TypeOrSpread]>>
Returns ()
fn extract(
&mut self,
span: Span,
expr: ReEvalMode<'_>,
ty: &Type,
kind: ExtractKind,
args: &[RExprOrSpread],
arg_types: &[TypeOrSpread],
spread_arg_types: &[TypeOrSpread],
type_args: Option<&TypeParamInstantiation>,
type_ann: Option<&Type>,
opts: CallOpts
) -> VResult<Type>
sourcefn call_type_element(
&mut self,
span: Span,
expr: ReEvalMode<'_>,
callee_ty: &Type,
type_params_of_type: Option<&TypeParamDecl>,
members: &[TypeElement],
kind: ExtractKind,
args: &[RExprOrSpread],
arg_types: &[TypeOrSpread],
spread_arg_types: &[TypeOrSpread],
type_args: Option<&TypeParamInstantiation>,
type_ann: Option<&Type>
) -> VResult<Type>
fn call_type_element(
&mut self,
span: Span,
expr: ReEvalMode<'_>,
callee_ty: &Type,
type_params_of_type: Option<&TypeParamDecl>,
members: &[TypeElement],
kind: ExtractKind,
args: &[RExprOrSpread],
arg_types: &[TypeOrSpread],
spread_arg_types: &[TypeOrSpread],
type_args: Option<&TypeParamInstantiation>,
type_ann: Option<&Type>
) -> VResult<Type>
Search for members and returns if there’s a match
fn check_method_call(
&mut self,
span: Span,
expr: ReEvalMode<'_>,
c: &MethodSignature,
type_args: Option<&TypeParamInstantiation>,
args: &[RExprOrSpread],
arg_types: &[TypeOrSpread],
spread_arg_types: &[TypeOrSpread],
type_ann: Option<&Type>
) -> VResult<Type>
pub(super) fn extract_callee_candidates(
&mut self,
span: Span,
kind: ExtractKind,
callee: &Type
) -> VResult<Vec<CallCandidate>>
fn get_best_return_type(
&mut self,
span: Span,
expr: ReEvalMode<'_>,
callee: Type,
kind: ExtractKind,
type_args: Option<&TypeParamInstantiation>,
args: &[RExprOrSpread],
arg_types: &[TypeOrSpread],
spread_arg_types: &[TypeOrSpread],
type_ann: Option<&Type>,
opts: SelectOpts
) -> VResult<Type>
fn validate_arg_count(
&mut self,
span: Span,
params: &[FnParam],
args: &[RExprOrSpread],
arg_types: &[TypeOrSpread],
spread_arg_types: &[TypeOrSpread]
) -> VResult<()>
fn validate_arg_count_spread(
&mut self,
args: &[RExprOrSpread],
arg_types: &[TypeOrSpread],
params: &[FnParam],
min_param: usize
) -> VResult<()>
sourcefn select_and_invoke(
&mut self,
span: Span,
kind: ExtractKind,
expr: ReEvalMode<'_>,
candidates: &[CallCandidate],
type_args: Option<&TypeParamInstantiation>,
args: &[RExprOrSpread],
arg_types: &[TypeOrSpread],
spread_arg_types: &[TypeOrSpread],
type_ann: Option<&Type>,
opts: SelectOpts
) -> VResult<Option<Type>>
fn select_and_invoke(
&mut self,
span: Span,
kind: ExtractKind,
expr: ReEvalMode<'_>,
candidates: &[CallCandidate],
type_args: Option<&TypeParamInstantiation>,
args: &[RExprOrSpread],
arg_types: &[TypeOrSpread],
spread_arg_types: &[TypeOrSpread],
type_ann: Option<&Type>,
opts: SelectOpts
) -> VResult<Option<Type>>
Returns None if nothing matched.
sourcefn get_return_type(
&mut self,
span: Span,
kind: ExtractKind,
expr: ReEvalMode<'_>,
type_params: Option<&[TypeParam]>,
params: &[FnParam],
ret_ty: Type,
type_args: Option<&TypeParamInstantiation>,
args: &[RExprOrSpread],
arg_types: &[TypeOrSpread],
spread_arg_types: &[TypeOrSpread],
type_ann: Option<&Type>
) -> VResult<Type>
fn get_return_type(
&mut self,
span: Span,
kind: ExtractKind,
expr: ReEvalMode<'_>,
type_params: Option<&[TypeParam]>,
params: &[FnParam],
ret_ty: Type,
type_args: Option<&TypeParamInstantiation>,
args: &[RExprOrSpread],
arg_types: &[TypeOrSpread],
spread_arg_types: &[TypeOrSpread],
type_ann: Option<&Type>
) -> VResult<Type>
Returns the return type of function. This method should be called only for final step because it emits errors instead of returning them.
fn validate_arg_types(
&mut self,
params: &[FnParam],
spread_arg_types: &[TypeOrSpread],
is_generic: bool
)
sourcefn add_call_facts(
&mut self,
params: &[FnParam],
args: &[RExprOrSpread],
ret_ty: &mut Type
)
fn add_call_facts(
&mut self,
params: &[FnParam],
args: &[RExprOrSpread],
ret_ty: &mut Type
)
Note:
function isSubscriber(val: any): val is DummySubscriber;
const observerOrNext: () => void | Subscriber;
const subscriber = isSubscriber(observerOrNext) ? observerOrNext : new SafeSubscriber();
should make type of subscriber
SafeSubscriber
, not Subscriber
.
I (kdy1) don’t know why.
fn narrow_with_predicate(
&mut self,
span: Span,
orig_ty: &Type,
new_ty: Type
) -> VResult<Type>
fn store_call_fact_for_var(&mut self, span: Span, var_name: Id, new_ty: &Type)
pub(crate) fn validate_type_args_count(
&mut self,
span: Span,
type_params: Option<&[TypeParam]>,
type_args: Option<&TypeParamInstantiation>
) -> VResult<()>
fn is_subtype_in_fn_call(&mut self, span: Span, arg: &Type, param: &Type) -> bool
sourcefn check_call_args(
&mut self,
span: Span,
type_params: Option<&[TypeParam]>,
params: &[FnParam],
type_args: Option<&TypeParamInstantiation>,
args: &[RExprOrSpread],
arg_types: &[TypeOrSpread],
spread_arg_types: &[TypeOrSpread]
) -> ArgCheckResult
fn check_call_args(
&mut self,
span: Span,
type_params: Option<&[TypeParam]>,
params: &[FnParam],
type_args: Option<&TypeParamInstantiation>,
args: &[RExprOrSpread],
arg_types: &[TypeOrSpread],
spread_arg_types: &[TypeOrSpread]
) -> ArgCheckResult
This method return Err if call is invalid
Implementation notes
anyAssignabilityInInheritance.ts
says any, not a subtype of number so it skips that overload, is a subtype of itself so it picks second (if truly ambiguous it would pick first overload)
fn apply_type_ann_from_callee(
&mut self,
span: Span,
kind: ExtractKind,
args: &[RExprOrSpread],
callee: &Type,
type_args: Option<&TypeParamInstantiation>,
type_ann_for_return_type: Option<&Type>
) -> VResult<()>
pub(crate) fn apply_type_ann_to_expr(
&mut self,
arg: &RExpr,
type_ann: &Type
) -> VResult<()>
fn validate_args(&mut self, args: &[RExprOrSpread]) -> VResult<Vec<TypeOrSpread>>
sourcepub(crate) fn apply_fn_type_ann<'a>(
&mut self,
span: Span,
fn_node_id: NodeId,
params: impl Iterator<Item = &'a RPat> + Clone,
type_ann: Option<&Type>
)
pub(crate) fn apply_fn_type_ann<'a>(
&mut self,
span: Span,
fn_node_id: NodeId,
params: impl Iterator<Item = &'a RPat> + Clone,
type_ann: Option<&Type>
)
fn_node_id
should be NodeId of stc_ts_ast_rnode::RFunction or
stc_ts_ast_rnode::RArrowExpr
fn get_jsx_intrinsic_element(&mut self, span: Span, sym: &JsWord) -> VResult<Type>
fn get_jsx_intrinsic_element_list(&mut self, span: Span) -> VResult<Option<Type>>
fn get_jsx_namespace(&mut self) -> Option<Type>
fn validate_jsx_attrs(
&mut self,
jsx_element_span: Span,
name: &ResolvedJsxName,
attrs: &[RJSXAttrOrSpread]
) -> VResult<()>
sourcepub(super) fn normalize_union(&mut self, ty: &mut Type, preserve_specified: bool)
pub(super) fn normalize_union(&mut self, ty: &mut Type, preserve_specified: bool)
Object literals in unions are normalized upon widening.
var a = [{ a: 0 }, { a: 1, b: "x" }];
Type of a
in the code above is { a: number, b?: undefined } | { a:number, b: string }
.
pub(crate) fn validate_type_literals(&mut self, ty: &Type, is_type_ann: bool)
pub(crate) fn report_errors_for_mixed_optional_method_signatures(
&mut self,
elems: &[TypeElement]
)
fn append_prop_or_spread_to_type(
&mut self,
known_keys: &mut Vec<Key>,
to: Type,
prop: &RPropOrSpread,
object_type: Option<&Type>
) -> VResult<Type>
pub(crate) fn is_always_undefined(&mut self, ty: &Type) -> bool
sourcepub(crate) fn append_type(
&mut self,
span: Span,
to: Type,
rhs: Type,
opts: AppendTypeOpts
) -> VResult<Type>
pub(crate) fn append_type(
&mut self,
span: Span,
to: Type,
rhs: Type,
opts: AppendTypeOpts
) -> VResult<Type>
If rhs is an union type, return type will be union.
{ a: number } + ( {b: number} | { c: number } )
=> { a: number, b: number } | { a: number, c: number }
pub(crate) fn append_type_element(
&mut self,
to: Type,
rhs: TypeElement
) -> VResult<Type>
sourcefn validate_type_cast(
&mut self,
span: Span,
orig_ty: Type,
casted_ty: Type
) -> VResult<Type>
fn validate_type_cast(
&mut self,
span: Span,
orig_ty: Type,
casted_ty: Type
) -> VResult<Type>
var unionTuple3: [number, string | number] = [10, "foo"];
var unionTuple4 = <[number, number]>unionTuple3;
is valid, while
var unionTuple3: [number, string | number] = [10, "foo"];
var unionTuple4: [number, number] = unionTuple3;
results in error.
fn validate_type_cast_inner(
&mut self,
span: Span,
orig: &Type,
casted: &Type
) -> VResult<()>
pub(crate) fn has_overlap(
&mut self,
span: Span,
l: &Type,
r: &Type,
opts: CastableOpts
) -> VResult<bool>
sourcepub(crate) fn castable(
&mut self,
span: Span,
from: &Type,
to: &Type,
opts: CastableOpts
) -> VResult<bool>
pub(crate) fn castable(
&mut self,
span: Span,
from: &Type,
to: &Type,
opts: CastableOpts
) -> VResult<bool>
Parameters
l
: fromr
: to
fn validate_delete_operand(&mut self, arg: &RExpr) -> VResult<()>
fn validate_unary_expr_inner(
&mut self,
span: Span,
op: UnaryOp,
arg_expr: &RExpr,
arg: &Type
)
fn is_update_operand_valid(&mut self, arg: &Type) -> VResult<bool>
sourcefn can_rhs_be_tuple(&mut self, left: &RPat) -> bool
fn can_rhs_be_tuple(&mut self, left: &RPat) -> bool
Returns true
if a rhs expression of the assignment expression can be
a tuple.
pub(crate) fn validate_key(
&mut self,
prop: &RExpr,
computed: bool
) -> VResult<Key>
sourcepub(crate) fn key_matches(
&mut self,
span: Span,
declared: &Key,
cur: &Key,
allow_union: bool
) -> bool
pub(crate) fn key_matches(
&mut self,
span: Span,
declared: &Key,
cur: &Key,
allow_union: bool
) -> bool
fn check_if_type_matches_key(
&mut self,
span: Span,
declared: &Key,
key_ty: &Type,
allow_union: bool
) -> bool
fn access_property_of_type_elements(
&mut self,
span: Span,
obj: &Type,
prop: &Key,
type_mode: TypeOfMode,
members: &[TypeElement],
opts: AccessPropertyOpts
) -> VResult<Option<Type>>
pub(super) fn access_property(
&mut self,
span: Span,
obj: &Type,
prop: &Key,
type_mode: TypeOfMode,
id_ctx: IdCtx,
opts: AccessPropertyOpts
) -> VResult<Type>
fn access_property_inner(
&mut self,
span: Span,
obj: &Type,
prop: &Key,
type_mode: TypeOfMode,
id_ctx: IdCtx,
opts: AccessPropertyOpts
) -> VResult<Type>
sourcefn type_to_query_if_required(&mut self, span: Span, i: &RIdent, ty: Type) -> Type
fn type_to_query_if_required(&mut self, span: Span, i: &RIdent, ty: Type) -> Type
TODO(kdy1): Clarify this.
sourcepub(crate) fn expand_generics_with_type_args(
&mut self,
span: Span,
ty: Type,
type_args: &TypeParamInstantiation
) -> VResult<Type>
pub(crate) fn expand_generics_with_type_args(
&mut self,
span: Span,
ty: Type,
type_args: &TypeParamInstantiation
) -> VResult<Type>
Expand type parameters using type_args
.
pub(super) fn type_of_name(
&mut self,
span: Span,
name: &Name,
type_mode: TypeOfMode,
type_args: Option<&TypeParamInstantiation>
) -> VResult<Type>
sourcepub(super) fn type_of_var(
&mut self,
i: &RIdent,
type_mode: TypeOfMode,
type_args: Option<&TypeParamInstantiation>
) -> VResult<Type>
pub(super) fn type_of_var(
&mut self,
i: &RIdent,
type_mode: TypeOfMode,
type_args: Option<&TypeParamInstantiation>
) -> VResult<Type>
Returned type reflects conditional type facts.
sourcefn type_of_raw_var(&mut self, i: &RIdent, type_mode: TypeOfMode) -> VResult<Type>
fn type_of_raw_var(&mut self, i: &RIdent, type_mode: TypeOfMode) -> VResult<Type>
Returned type does not reflects conditional type facts. (like Truthy / exclusion)
pub(crate) fn type_of_ts_entity_name(
&mut self,
span: Span,
n: &RExpr,
type_args: Option<&TypeParamInstantiation>
) -> VResult<Type>
fn type_of_ts_entity_name_inner(
&mut self,
span: Span,
n: &RExpr,
type_args: Option<&TypeParamInstantiation>
) -> VResult<Type>
sourcefn type_of_member_expr(
&mut self,
expr: &RMemberExpr,
type_mode: TypeOfMode,
include_optional_chaining_undefined: bool
) -> VResult<Type>
fn type_of_member_expr(
&mut self,
expr: &RMemberExpr,
type_mode: TypeOfMode,
include_optional_chaining_undefined: bool
) -> VResult<Type>
TODO(kdy1): Expand type arguments if provided.
sourcefn type_of_super_prop_expr(
&mut self,
expr: &RSuperPropExpr,
type_mode: TypeOfMode
) -> VResult<Type>
fn type_of_super_prop_expr(
&mut self,
expr: &RSuperPropExpr,
type_mode: TypeOfMode
) -> VResult<Type>
TODO(kdy1): Expand type arguments if provided.
fn prefer_tuple(&mut self, type_ann: Option<&Type>) -> bool
pub(crate) fn report_error_for_super_refs_without_supers(
&mut self,
span: Span,
is_super_call: bool
)
pub(crate) fn report_error_for_super_reference_in_compute_keys(
&mut self,
span: Span,
is_super_call: bool
)
fn prefer_tuple_type_elements(&mut self, elems: &[TypeElement]) -> bool
pub(crate) fn expand_return_type_of_fn(
&mut self,
ret_ty: &mut Type
) -> VResult<()>
pub(crate) fn fn_to_type_element(&mut self, f: &Function) -> VResult<TypeElement>
sourcepub(super) fn may_generalize(&self, ty: &Type) -> bool
pub(super) fn may_generalize(&self, ty: &Type) -> bool
TODO(kdy1): Remove this.
Check if it’s okay to generalize ty
.
pub(super) fn prevent_inference_while_simplifying(&self, ty: &mut Type)
pub(super) fn simplify(&self, ty: Type) -> Type
pub(in analyzer) fn instantiate_type_params_using_args(
&mut self,
span: Span,
type_params: &TypeParamDecl,
type_args: &TypeParamInstantiation
) -> VResult<FxHashMap<Id, Type>>
sourcepub(in analyzer) fn expand_type_params<T>(
&mut self,
params: &FxHashMap<Id, Type>,
ty: T,
opts: ExpandGenericOpts
) -> VResult<T>where
T: for<'aa> FoldWith<GenericExpander<'aa>> + Fix,
pub(in analyzer) fn expand_type_params<T>(
&mut self,
params: &FxHashMap<Id, Type>,
ty: T,
opts: ExpandGenericOpts
) -> VResult<T>where
T: for<'aa> FoldWith<GenericExpander<'aa>> + Fix,
This methods handle special types like mapped type.
e.g.
type BadNested
z T extends { x: infer P extends number ? infer P : string; } ? P : never
sourcepub(super) fn infer_from_matching_types(
&mut self,
span: Span,
inferred: &mut InferData,
sources: &[Type],
targets: &[Type],
matches: impl Fn(&mut Analyzer<'_, '_>, &Type, &Type) -> bool,
opts: InferTypeOpts
) -> VResult<(Vec<Type>, Vec<Type>)>
pub(super) fn infer_from_matching_types(
&mut self,
span: Span,
inferred: &mut InferData,
sources: &[Type],
targets: &[Type],
matches: impl Fn(&mut Analyzer<'_, '_>, &Type, &Type) -> bool,
opts: InferTypeOpts
) -> VResult<(Vec<Type>, Vec<Type>)>
Ported from inferFromMatchingTypes
of tsc
.
sourcepub(super) fn infer_type_using_union(
&mut self,
span: Span,
inferred: &mut InferData,
param: &Union,
arg: &Type,
opts: InferTypeOpts
) -> VResult<()>
pub(super) fn infer_type_using_union(
&mut self,
span: Span,
inferred: &mut InferData,
param: &Union,
arg: &Type,
opts: InferTypeOpts
) -> VResult<()>
Ported from tsc
.
sourcepub(super) fn infer_to_multiple_types(
&mut self,
span: Span,
inferred: &mut InferData,
source: &Type,
targets: &[Type],
is_target_union: bool,
opts: InferTypeOpts
) -> VResult<()>
pub(super) fn infer_to_multiple_types(
&mut self,
span: Span,
inferred: &mut InferData,
source: &Type,
targets: &[Type],
is_target_union: bool,
opts: InferTypeOpts
) -> VResult<()>
Ported from inferToMultipleTypes
of tsc
.
sourcepub(super) fn infer_from_types(
&mut self,
span: Span,
inferred: &mut InferData,
source: &Type,
target: &Type,
opts: InferTypeOpts
) -> VResult<()>
pub(super) fn infer_from_types(
&mut self,
span: Span,
inferred: &mut InferData,
source: &Type,
target: &Type,
opts: InferTypeOpts
) -> VResult<()>
Ported from inferFromTypes
of tsc
.
pub(super) fn infer_with_priority(
&mut self,
span: Span,
inferred: &mut InferData,
source: &Type,
target: &Type,
new_priority: InferencePriority,
opts: InferTypeOpts
) -> VResult<()>
sourcepub(super) fn infer_to_multiple_types_with_priority(
&mut self,
span: Span,
inferred: &mut InferData,
source: &Type,
targets: &[Type],
new_priority: InferencePriority,
is_target_union: bool,
opts: InferTypeOpts
) -> VResult<()>
pub(super) fn infer_to_multiple_types_with_priority(
&mut self,
span: Span,
inferred: &mut InferData,
source: &Type,
targets: &[Type],
new_priority: InferencePriority,
is_target_union: bool,
opts: InferTypeOpts
) -> VResult<()>
inferToMultipleTypesWithPriority
sourcepub(super) fn infer_from_contravariant_types(
&mut self,
span: Span,
inferred: &mut InferData,
source: &Type,
target: &Type,
opts: InferTypeOpts
) -> VResult<()>
pub(super) fn infer_from_contravariant_types(
&mut self,
span: Span,
inferred: &mut InferData,
source: &Type,
target: &Type,
opts: InferTypeOpts
) -> VResult<()>
Ported from inferFromContravariantTypes
of tsc
.
sourcefn get_inference_info_for_type<'a>(
&mut self,
inferred: &'a mut InferData,
ty: &Type
) -> Option<&'a mut InferenceInfo>
fn get_inference_info_for_type<'a>(
&mut self,
inferred: &'a mut InferData,
ty: &Type
) -> Option<&'a mut InferenceInfo>
Ported from getInferenceInfoForType
of tsc
.
sourcefn get_single_type_variable_from_intersection_types(
&mut self,
span: Span,
inferred: &mut InferData,
types: &[Type]
) -> Option<Type>
fn get_single_type_variable_from_intersection_types(
&mut self,
span: Span,
inferred: &mut InferData,
types: &[Type]
) -> Option<Type>
Ported from getSingleTypeVariableFromIntersectionTypes
of tsc
.
sourcepub(super) fn infer_to_tpl_lit_type(
&mut self,
span: Span,
inferred: &mut InferData,
source: &Type,
target: &TplType,
opts: InferTypeOpts
) -> VResult<()>
pub(super) fn infer_to_tpl_lit_type(
&mut self,
span: Span,
inferred: &mut InferData,
source: &Type,
target: &TplType,
opts: InferTypeOpts
) -> VResult<()>
Ported from inferToTemplateLiteralType
of tsc
.
sourcepub(crate) fn infer_types_from_tpl_lit_type(
&mut self,
span: Span,
source: &Type,
target: &TplType
) -> VResult<Option<Vec<Type>>>
pub(crate) fn infer_types_from_tpl_lit_type(
&mut self,
span: Span,
source: &Type,
target: &TplType
) -> VResult<Option<Vec<Type>>>
Ported from inferTypesFromTemplateLiteralType
of tsc
.
sourcefn infer_from_lit_parts_to_tpl_lit(
&mut self,
span: Span,
source_texts: &[Atom],
source_types: &[Type],
target: &TplType
) -> VResult<Option<Vec<Type>>>
fn infer_from_lit_parts_to_tpl_lit(
&mut self,
span: Span,
source_texts: &[Atom],
source_types: &[Type],
target: &TplType
) -> VResult<Option<Vec<Type>>>
Ported from inferFromLiteralPartsToTemplateLiteral
of tsc
.
This function infers from the text parts and type parts of a source literal to a target template literal. The number of text parts is always one more than the number of type parts, and a source string literal is treated as a source with one text part and zero type parts. The function returns an array of inferred string or template literal types corresponding to the placeholders in the target template literal, or undefined if the source doesn’t match the target.
We first check that the starting source text part matches the starting
target text part, and that the ending source text part ends matches
the ending target text part. We then iterate through the remaining
target text parts, finding a match for each in the source and
inferring string or template literal types created from the segments of
the source that occur between the matches. During this iteration,
seg holds the index of the current text part in the sourceTexts
array and pos holds the current character position in the current text
part.
Consider inference from type <<${string}>.<${number}-${number}>>
to
type <${string}.${string}>
, i.e. sourceTexts = [‘<<’, ‘>.<’,
‘-’, ‘>>’] sourceTypes = [string, number, number]
target.texts = [‘<’, ‘.’, ‘>’]
We first match ‘<’ in the target to the start of ‘<<’ in the source and
‘>’ in the target to the end of ‘>>’ in the source. The first match
for the ‘.’ in target occurs at character 1 in the source text part at
index 1, and thus the first inference is the template literal type
<${string}>
. The remainder of the source makes up the second
inference, the template literal type <${number}-${number}>
.
pub(super) fn insert_inferred(
&mut self,
span: Span,
inferred: &mut InferData,
tp: &TypeParam,
ty: Cow<'_, Type>,
opts: InferTypeOpts
) -> VResult<()>
sourcepub(super) fn insert_inferred_raw(
&mut self,
span: Span,
inferred: &mut InferData,
name: Id,
ty: Cow<'_, Type>,
opts: InferTypeOpts
) -> VResult<()>
pub(super) fn insert_inferred_raw(
&mut self,
span: Span,
inferred: &mut InferData,
name: Id,
ty: Cow<'_, Type>,
opts: InferTypeOpts
) -> VResult<()>
Rules
Type literal
If one of type literal is specified
according to the metadata, type
inference is done.
See:
declare function f<T>(...items: T[]): T;
declare let data: { a: 1, b: "abc", c: true };
declare let data2: { b: "foo", c: true };
// Not specified
let e1 = f({ a: 1, b: 2 }, { a: "abc" }, {});
let e2 = f({}, { a: "abc" }, { a: 1, b: 2 });
// Type inference is done if at least one element is specified.
let e3 = f(data, { a: 2 }); // Error
let e4 = f({ a: 2 }, data); // Error
let e5 = f(data, data2); // Error
pub(super) fn upsert_inferred(
&mut self,
span: Span,
inferred: &mut InferData,
name: Id,
arg: &Type,
opts: InferTypeOpts
) -> VResult<()>
sourcepub(crate) fn infer_type_with_types(
&mut self,
span: Span,
type_params: &[TypeParam],
param: &Type,
arg: &Type,
opts: InferTypeOpts
) -> VResult<FxHashMap<Id, Type>>
pub(crate) fn infer_type_with_types(
&mut self,
span: Span,
type_params: &[TypeParam],
param: &Type,
arg: &Type,
opts: InferTypeOpts
) -> VResult<FxHashMap<Id, Type>>
Infer types, using param
and arg
.
sourcepub(super) fn infer_builtin(
&mut self,
span: Span,
inferred: &mut InferData,
param: &Type,
arg: &Type,
opts: InferTypeOpts
) -> Option<VResult<()>>
pub(super) fn infer_builtin(
&mut self,
span: Span,
inferred: &mut InferData,
param: &Type,
arg: &Type,
opts: InferTypeOpts
) -> Option<VResult<()>>
Handle some special builtin types
pub(super) fn infer_type_using_interface(
&mut self,
span: Span,
inferred: &mut InferData,
param: &Interface,
arg: &Type,
opts: InferTypeOpts
) -> VResult<()>
fn infer_type_using_interface_and_interface(
&mut self,
span: Span,
inferred: &mut InferData,
param: &Interface,
arg: &Interface,
opts: InferTypeOpts
) -> VResult<()>
sourcepub(super) fn infer_type_using_type_lit_and_type_lit(
&mut self,
span: Span,
inferred: &mut InferData,
param: &TypeLit,
arg: &TypeLit,
opts: InferTypeOpts
) -> VResult<()>
pub(super) fn infer_type_using_type_lit_and_type_lit(
&mut self,
span: Span,
inferred: &mut InferData,
param: &TypeLit,
arg: &TypeLit,
opts: InferTypeOpts
) -> VResult<()>
Compare fields.
sourcepub(super) fn infer_type_by_converting_to_type_lit(
&mut self,
span: Span,
inferred: &mut InferData,
param: &Type,
arg: &Type,
opts: InferTypeOpts
) -> VResult<bool>
pub(super) fn infer_type_by_converting_to_type_lit(
&mut self,
span: Span,
inferred: &mut InferData,
param: &Type,
arg: &Type,
opts: InferTypeOpts
) -> VResult<bool>
Returns Ok(true)
if this method know how to infer types.
fn infer_type_using_type_elements_and_type_elements(
&mut self,
span: Span,
inferred: &mut InferData,
param: &[TypeElement],
arg: &[TypeElement],
opts: InferTypeOpts
) -> VResult<()>
pub(super) fn infer_type_using_readonly(
&mut self,
span: Span,
inferred: &mut InferData,
param: &Readonly,
arg: &Type,
opts: InferTypeOpts
) -> VResult<()>
pub(super) fn infer_types_using_class(
&mut self,
span: Span,
inferred: &mut InferData,
param: &Class,
arg: &Class,
opts: InferTypeOpts
) -> VResult<()>
pub(super) fn infer_types_using_class_def(
&mut self,
span: Span,
inferred: &mut InferData,
param: &ClassDef,
arg: &ClassDef,
opts: InferTypeOpts
) -> VResult<()>
pub(super) fn finalize_inference(
&self,
span: Span,
type_params: &[TypeParam],
inferred: InferData
) -> InferTypeResult
sourcefn replace_null_or_undefined_while_defaulting_to_any(&self, ty: &mut Type)
fn replace_null_or_undefined_while_defaulting_to_any(&self, ty: &mut Type)
TODO(kdy1): Handle union
pub(super) fn prevent_generalization_of_top_level_types(
&self,
type_params: &[TypeParam],
ret_ty: Option<&Type>,
inferred: &mut InferData,
is_from_type_ann: bool
)
sourcepub(super) fn prevent_generalization_of_inferred_types(
&mut self,
type_params: &[TypeParam],
inferred: &mut InferData,
is_from_type_ann: bool
)
pub(super) fn prevent_generalization_of_inferred_types(
&mut self,
type_params: &[TypeParam],
inferred: &mut InferData,
is_from_type_ann: bool
)
Prevent generalizations if a type parameter extends literal.
sourcepub(super) fn infer_arg_types(
&mut self,
span: Span,
base: Option<&TypeParamInstantiation>,
type_params: &[TypeParam],
params: &[FnParam],
args: &[TypeOrSpread],
default_ty: Option<&Type>,
ret_ty: Option<&Type>,
ret_ty_type_ann: Option<&Type>,
opts: InferTypeOpts
) -> VResult<InferTypeResult>
pub(super) fn infer_arg_types(
&mut self,
span: Span,
base: Option<&TypeParamInstantiation>,
type_params: &[TypeParam],
params: &[FnParam],
args: &[TypeOrSpread],
default_ty: Option<&Type>,
ret_ty: Option<&Type>,
ret_ty_type_ann: Option<&Type>,
opts: InferTypeOpts
) -> VResult<InferTypeResult>
This method accepts Option<&TypeParamInstantiation> because user may provide only some of type arguments.
sourcepub(super) fn infer_ts_infer_types(
&mut self,
span: Span,
base: &Type,
concrete: &Type,
opts: InferTypeOpts
) -> VResult<FxHashMap<Id, Type>>
pub(super) fn infer_ts_infer_types(
&mut self,
span: Span,
base: &Type,
concrete: &Type,
opts: InferTypeOpts
) -> VResult<FxHashMap<Id, Type>>
Handles infer U
.
sourcefn infer_type(
&mut self,
span: Span,
inferred: &mut InferData,
param: &Type,
arg: &Type,
opts: InferTypeOpts
) -> VResult<()>
fn infer_type(
&mut self,
span: Span,
inferred: &mut InferData,
param: &Type,
arg: &Type,
opts: InferTypeOpts
) -> VResult<()>
Inference rule
-
We iterate over parameters and arguments in order.
-
If newly inferred type is not compatible with the previous one, we don’t store it.
compatible
here means the previous type is assignable to the newly inferred type. -
If there’s
any
orunknown
, those are used because all types arecompatible
with them.
If any
and unknown
co-exist, the last one is selected.
-
{}
and an empty interface work just likeany
orunknown
. It’s because almost all types arecompatible
with it, so the same rule applies. Butany
orunknown
is preferred over{}
. -
If a parameter of a closure has an explicit type, the
compatibility
rule applies. But some types like the built-inObject
are exceptions and those are ignored. i.e. The inferred types are not changed toObject
. -
The return type of a closure does not have effect on the inference, iff it’s a direct function expression.
Postprocess
- If there was noe error and if there’s no constraints like
extends string
norextends number
, the inferred types are generalized.
function foo<T>(x: { bar: T; baz: T }) {
return x;
}
declare function fn1(): void;
declare function f2(): string;
declare class C1 {
prop: string
}
declare class C2 {
c2prop: number
}
interface I1 {
s: string
}
declare const us: unique symbol
declare var i1: I1
declare var c1: C1
declare var c2: C2
declare var n: number
foo({ bar: 1, baz: '' }); // Error on baz (number is selected)
foo({ bar: '', baz: 1 }); // Error on baz (string is selected)
foo({ bar: '', baz: n }); // Error on baz (string is selected)
foo({ bar: Symbol.iterator, baz: 5 }) // Error on baz (symbol is selected)
foo({ bar: us, baz: 5 }) // Error on baz (unique symbol is selected)
foo({ bar: [], baz: '' }); // Error on bar (string is selected)
foo({ bar: {}, baz: '' }); // Error on bar (string is selected)
declare var u: string | number
foo({ bar: 1, baz: u }) // Ok
foo({ bar: {}, baz: u }) // Error on bar (string | number is selected)
foo({ bar: i1, baz: 5 }) // Error on baz (I1 is selected)
foo({ bar: 5, baz: i1 }) // Error on baz (number is selected)
foo({ bar: 5, baz: fn1 }) // Error on baz (number is selected)
foo({ bar: 5, baz: i1 }) // Error on baz (number is selected)
foo({ bar: 1, baz: c2 }) // Error on baz (number is selected)
foo({ bar: c1, baz: 1 }) // Error on baz (C1 is selected)
foo({ bar: c1, baz: c2 }) // Error on baz (C1 is selected)
foo({ bar: i1, baz: c1 }) // Error on baz (I1 is selected)
foo({ bar: c1, baz: i1 }) // Error on baz (C1 is selected)
function arr<T>(x: T[]) {
return x;
}
arr([1, '']); // Ok
arr(['', 1]); // Ok
arr([Symbol.iterator, 5]) // Ok
arr([us, 5]) // Ok
arr([[], '']); // Ok
arr([{}, '']); // Ok
arr([1, u]) // Ok
arr([{}, u]) // Ok
sourcefn infer_type_inner(
&mut self,
span: Span,
inferred: &mut InferData,
param: &Type,
arg: &Type,
opts: InferTypeOpts
) -> VResult<()>
fn infer_type_inner(
&mut self,
span: Span,
inferred: &mut InferData,
param: &Type,
arg: &Type,
opts: InferTypeOpts
) -> VResult<()>
Infer types, so that param
has same type as arg
.
TODO(kdy1): Optimize
fn infer_type_using_mapped_type(
&mut self,
span: Span,
inferred: &mut InferData,
param: &Mapped,
arg: &Type,
opts: InferTypeOpts
) -> VResult<bool>
fn infer_type_using_tuple_and_tuple(
&mut self,
span: Span,
inferred: &mut InferData,
param: &Tuple,
param_ty: &Type,
arg: &Tuple,
arg_ty: &Type,
opts: InferTypeOpts
) -> VResult<()>
fn infer_type_of_fn_param(
&mut self,
span: Span,
inferred: &mut InferData,
param: &FnParam,
arg: &FnParam,
opts: InferTypeOpts
) -> VResult<()>
fn infer_type_of_fn_params(
&mut self,
span: Span,
inferred: &mut InferData,
params: &[FnParam],
args: &[FnParam],
opts: InferTypeOpts
) -> VResult<()>
fn rename_inferred(
&mut self,
span: Span,
inferred: &mut InferData,
arg_type_params: &TypeParamDecl
) -> VResult<()>
pub(super) fn rename_type_params(
&mut self,
span: Span,
ty: Type,
type_ann: Option<&Type>
) -> VResult<Type>
pub(super) fn validate_stmts_with_hoisting<T>(&mut self, stmts: &Vec<&T>)where
T: AsModuleDecl + ModuleItemOrStmt + VisitWith<Self> + From<RStmt> + HasNodeId + Sortable<Id = TypedId>,
sourcepub(super) fn validate_stmts_and_collect<T>(&mut self, stmts: &Vec<&T>)where
T: AsModuleDecl + ModuleItemOrStmt + VisitWith<Self> + From<RStmt> + HasNodeId + Sortable<Id = TypedId>,
pub(super) fn validate_stmts_and_collect<T>(&mut self, stmts: &Vec<&T>)where
T: AsModuleDecl + ModuleItemOrStmt + VisitWith<Self> + From<RStmt> + HasNodeId + Sortable<Id = TypedId>,
A special method is require code like
function foo() {
return a;
}
const a = 5;
const b = foo();
sourcefn reorder_stmts<T>(&mut self, stmts: &[&T]) -> (Vec<usize>, FxHashSet<usize>)where
T: AsModuleDecl + Sortable<Id = TypedId>,
fn reorder_stmts<T>(&mut self, stmts: &[&T]) -> (Vec<usize>, FxHashSet<usize>)where
T: AsModuleDecl + Sortable<Id = TypedId>,
Returns (the order of evaluation, skipped index). This methods is used to handle hoisting properly.
Example
The method will return [1, 0]
for the code below.
function foo() {
return bar();
}
function bar (){
return 1;
}K
Note
This function prioritize types in order of
- no deps
- resolvable (non-circular)
- others
a.ts
:
import { B } from './b';
export type C = 5 | 10;
export type B = A;
b.ts
:
import A from './a';
export type C = 5 | 10;
export type B = A;
sourcepub(crate) fn get_imported_items(
&mut self,
span: Span,
dst: &JsWord
) -> (ModuleId, Type)
pub(crate) fn get_imported_items(
&mut self,
span: Span,
dst: &JsWord
) -> (ModuleId, Type)
Returns (dep_module, dep_types)
if an import is valid, and returns
(cur_mod_id, empty_data)
on import errors.
TODO: Make this returns None when import failed
pub(super) fn find_imported_var(&self, id: &Id) -> VResult<Option<Type>>
pub(crate) fn insert_import_info(
&mut self,
ctxt: ModuleId,
dep_module_id: ModuleId,
ty: Type
) -> VResult<()>
pub(super) fn load_normal_imports(
&mut self,
module_spans: Vec<(ModuleId, Span)>,
items: &Vec<&RModuleItem>
)
pub(crate) fn mark_as_implicitly_typed(&mut self, ty: &mut Type)
pub(crate) fn is_implicitly_typed(&self, ty: &Type) -> bool
pub(crate) fn default_type_for_pat(&mut self, pat: &RPat) -> VResult<Type>
fn validate_pat(&mut self, p: &RPat) -> VResult<FnParam>
sourcepub(crate) fn report_error_for_usage_of_type_param_of_declaring_class(
&mut self,
used_type_params: &[TypeParam],
span: Span
)
pub(crate) fn report_error_for_usage_of_type_param_of_declaring_class(
&mut self,
used_type_params: &[TypeParam],
span: Span
)
Computed properties should not use type parameters defined by the declaring class.
See: computedPropertyNames32_ES5.ts
fn is_type_valid_for_computed_key(&mut self, span: Span, ty: &Type) -> bool
fn validate_prop_inner(
&mut self,
prop: &RProp,
object_type: Option<&Type>
) -> VResult<TypeElement>
Ported from isTypeRelatedTo
of tsc
.
TODO: Implement
Ported from isSimpleTypeRelatedTo
of tsc
.
TODO: Implement
Ported from checkTypeRelatedTo
of tsc
.
pub(crate) fn get_property_type_from_this(
&mut self,
span: Span,
p: &Id
) -> Option<Type>
sourcepub(crate) fn expand_this_in_type(&mut self, ty: &mut Type)
pub(crate) fn expand_this_in_type(&mut self, ty: &mut Type)
Expand this
contained in ty
.
sourcepub(crate) fn replace_invalid_type_params(&mut self, ty: &mut Type)
pub(crate) fn replace_invalid_type_params(&mut self, ty: &mut Type)
Convert type parameters declared in dead scopes to {}
.
This does not touch type parameters declared in parent scopes and this method should be called when a type had escaped a scope.
In this way, we can handle both of cases below.
Invalid assignment.
function foo<T, U>() {
var a: T;
var b: U;
a = b; // This is wrong.
}
This case is handled because type parameters are not touched (while we are analyzing function) by the method.
Escaping
function foo<T>() {}
function bar<T>() {}
var a = foo(); // type is {}
a = bar();
This method is called at the end of each call and each T
is converted
to {}
even though span hygiene differs.
fn is_type_param_dead(&mut self, name: &Id) -> bool
sourcepub(crate) fn add_vars(
&mut self,
pat: &RPat,
ty: Option<Type>,
actual: Option<Type>,
default: Option<Type>,
opts: DeclareVarsOpts
) -> VResult<Option<Type>>
pub(crate) fn add_vars(
&mut self,
pat: &RPat,
ty: Option<Type>,
actual: Option<Type>,
default: Option<Type>,
opts: DeclareVarsOpts
) -> VResult<Option<Type>>
TODO(kdy1): Rename to declare_vars
Parameters
actual
The type of actual value.
default
The type of default value specified by an assignment pattern.
pub(crate) fn exclude_props(
&mut self,
span: Span,
ty: &Type,
keys: &[Key]
) -> VResult<Type>
fn ensure_iterable(&mut self, span: Span, ty: Type) -> VResult<Type>
pub fn regist_destructure(
&mut self,
span: Span,
ty: Option<Type>,
des_key: Option<DestructureId>
) -> DestructureId
sourcepub(super) fn override_var(
&mut self,
kind: VarKind,
name: Id,
ty: Type
) -> VResult<()>
pub(super) fn override_var(
&mut self,
kind: VarKind,
name: Id,
ty: Type
) -> VResult<()>
Overrides a variable. Used for updating types.
sourcepub(super) fn expand(
&mut self,
span: Span,
ty: Type,
opts: ExpandOpts
) -> VResult<Type>
pub(super) fn expand(
&mut self,
span: Span,
ty: Type,
opts: ExpandOpts
) -> VResult<Type>
Expands
- Type alias
// TODO(kdy1): Add an option to expand union (this is required to assign)
expand_union
should be true if you are going to use it in assignment, and false if you are going to use it in user-visible stuffs (e.g. type annotation for .d.ts file)
pub(super) fn expand_type_params_using_scope(
&mut self,
ty: Type
) -> VResult<Type>
sourcepub(crate) fn expand_top_ref<'a>(
&mut self,
span: Span,
ty: Cow<'a, Type>,
opts: ExpandOpts
) -> VResult<Cow<'a, Type>>
pub(crate) fn expand_top_ref<'a>(
&mut self,
span: Span,
ty: Cow<'a, Type>,
opts: ExpandOpts
) -> VResult<Cow<'a, Type>>
Expands the type if it’s Type::Ref.
sourcepub(crate) fn store_unmergable_type_span(&mut self, id: Id, span: Span)
pub(crate) fn store_unmergable_type_span(&mut self, id: Id, span: Span)
This should be called after calling register_type
.
pub(super) fn register_type(&mut self, name: Id, ty: Type) -> Type
pub(super) fn resolve_typeof(
&mut self,
span: Span,
name: &RTsEntityName
) -> VResult<Type>
pub(super) fn find_var(&self, name: &Id) -> Option<&VarInfo>
pub(super) fn find_var_type(
&self,
name: &Id,
mode: TypeOfMode
) -> Option<Cow<'_, Type>>
pub fn find_type(&self, name: &Id) -> VResult<Option<ItemRef<'_, Type>>>
fn find_local_type(&self, name: &Id) -> Option<ItemRef<'_, Type>>
sourcepub(super) fn mark_var_as_truthy(&mut self, name: Id) -> VResult<()>
pub(super) fn mark_var_as_truthy(&mut self, name: Id) -> VResult<()>
TODO(kdy1): Restore this(?)
fn modify_var<F, Ret>(&mut self, name: Id, op: F) -> VResult<Ret>where
F: FnOnce(&mut VarInfo) -> VResult<Ret>,
pub fn get_destructor_unique_key(&self) -> DestructureId
pub fn declare_destructor(
&mut self,
span: Span,
ty: &Type,
key: DestructureId
) -> VResult<bool>
pub fn find_destructor(&self, key: DestructureId) -> Option<Cow<'_, Type>>
sourcepub fn declare_var(
&mut self,
span: Span,
kind: VarKind,
name: Id,
ty: Option<Type>,
actual_ty: Option<Type>,
initialized: bool,
allow_multiple: bool,
is_override: bool,
is_fn_decl_with_body: bool
) -> VResult<Option<Type>>
pub fn declare_var(
&mut self,
span: Span,
kind: VarKind,
name: Id,
ty: Option<Type>,
actual_ty: Option<Type>,
initialized: bool,
allow_multiple: bool,
is_override: bool,
is_fn_decl_with_body: bool
) -> VResult<Option<Type>>
If allow_multiple
is true and is_override
is false, the value type
is updated only if it’s temporary type (like typeof foo
while
validating foo
).
sourcefn validate_fn_overloads(
&mut self,
span: Span,
orig: &Type,
new: &Type,
kind: VarKind
) -> VResult<()>
fn validate_fn_overloads(
&mut self,
span: Span,
orig: &Type,
new: &Type,
kind: VarKind
) -> VResult<()>
Returns Err if overload is wrong.
sourcepub fn declare_complex_vars(
&mut self,
kind: VarKind,
pat: &RPat,
ty: Type,
actual_ty: Option<Type>,
default_ty: Option<Type>
) -> VResult<Option<Type>>
pub fn declare_complex_vars(
&mut self,
kind: VarKind,
pat: &RPat,
ty: Type,
actual_ty: Option<Type>,
default_ty: Option<Type>
) -> VResult<Option<Type>>
TODO(kdy1): Merge with declare_vars_*
pub(crate) fn mark_type_as_infer_type_container(&self, ty: &mut Type)
sourcepub(crate) fn prevent_expansion<T>(&self, ty: &mut T)where
T: VisitMutWith<ExpansionPreventer>,
pub(crate) fn prevent_expansion<T>(&self, ty: &mut T)where
T: VisitMutWith<ExpansionPreventer>,
Mark ty
as not expanded by default.
sourcepub(crate) fn allow_expansion<T>(&self, ty: &mut T)where
T: VisitMutWith<ExpansionPreventer>,
pub(crate) fn allow_expansion<T>(&self, ty: &mut T)where
T: VisitMutWith<ExpansionPreventer>,
Mark ty
as expandable. This has higher precedence than
prevent_expansion
.
pub(super) fn is_expansion_prevented(&self, ty: &Type) -> bool
pub(crate) fn report_error_for_wrong_top_level_ambient_fns(
&mut self,
nodes: &[RModuleItem]
)
sourcefn validate_loop_body_with_scope(
&mut self,
test: Option<&RExpr>,
body: &RStmt
) -> VResult<()>
fn validate_loop_body_with_scope(
&mut self,
test: Option<&RExpr>,
body: &RStmt
) -> VResult<()>
We evaluate loop bodies multiple time. But actually we don’t report errors
If type does not change due to a loop, we evaluate
fn validate_lhs_of_for_loop(
&mut self,
e: &RVarDeclOrPat,
elem_ty: &Type,
kind: ForHeadKind
)
fn validate_lhs_of_for_in_of_loop(
&mut self,
e: &RVarDeclOrPat,
kind: ForHeadKind
) -> VResult<()>
fn validate_lhs_of_for_in_of_loop_pat(
&mut self,
p: &RPat,
kind: ForHeadKind
) -> VResult<()>
fn validate_lhs_of_for_in_of_loop_expr(
&mut self,
e: &RExpr,
kind: ForHeadKind
) -> VResult<()>
fn get_element_type_of_for_in(&mut self, span: Span, rhs: &Type) -> VResult<Type>
fn check_for_of_in_loop(
&mut self,
span: Span,
left: &RVarDeclOrPat,
rhs: &RExpr,
kind: ForHeadKind,
body: &RStmt
)
fn check_for_infinite_loop(&mut self, test: &Type, body: &RStmt)
sourcepub(super) fn resolve_parent_interfaces(
&mut self,
parents: &[RTsExprWithTypeArgs],
is_for_interface: bool
)
pub(super) fn resolve_parent_interfaces(
&mut self,
parents: &[RTsExprWithTypeArgs],
is_for_interface: bool
)
Validate that parent interfaces are all resolved.
sourcepub(crate) fn is_type_closely_matched_by(
&mut self,
source: &Type,
target: &Type
) -> bool
pub(crate) fn is_type_closely_matched_by(
&mut self,
source: &Type,
target: &Type
) -> bool
isTypeCloselyMatchedBy
of tsc
.
sourcepub(crate) fn is_type_or_base_identical_to(
&mut self,
source: &Type,
target: &Type
) -> bool
pub(crate) fn is_type_or_base_identical_to(
&mut self,
source: &Type,
target: &Type
) -> bool
isTypeOrBaseIdenticalTo
of tsc
.
sourcepub(crate) fn is_type_identical_to(
&mut self,
source: &Type,
target: &Type
) -> bool
pub(crate) fn is_type_identical_to(
&mut self,
source: &Type,
target: &Type
) -> bool
isTypeIdenticalTo
of tsc
.
sourcepub(crate) fn is_type_assignable_to(
&mut self,
span: Span,
source: &Type,
target: &Type
) -> bool
pub(crate) fn is_type_assignable_to(
&mut self,
span: Span,
source: &Type,
target: &Type
) -> bool
Ported from isTypeAssignableTo
of tsc
.
sourcepub(crate) fn is_valid_num_str(&mut self, s: &str, round_trip_only: bool) -> bool
pub(crate) fn is_valid_num_str(&mut self, s: &str, round_trip_only: bool) -> bool
Ported from isValidNumberString
of tsc
.
sourcepub(crate) fn is_valid_big_int_str(
&mut self,
s: &str,
round_trip_only: bool
) -> bool
pub(crate) fn is_valid_big_int_str(
&mut self,
s: &str,
round_trip_only: bool
) -> bool
Ported from isValidBigIntString
of tsc
.
sourcepub(crate) fn is_member_of_string_mapping(
&mut self,
span: Span,
source: &Type,
target: &Type
) -> VResult<bool>
pub(crate) fn is_member_of_string_mapping(
&mut self,
span: Span,
source: &Type,
target: &Type
) -> VResult<bool>
Ported from isMemberOfStringMapping
of tsc
.
pub(crate) fn get_string_like_type_for_type<'a>(
&mut self,
ty: &'a Type
) -> Cow<'a, Type>
pub(crate) fn normalize_conditional<'a>(
&mut self,
actual_span: Span,
c: Conditional,
opts: NormalizeTypeOpts
) -> VResult<Cow<'a, Type>>
pub(crate) fn overwrite_conditional(
&mut self,
span: Span,
c: &Conditional
) -> Type
pub(crate) fn expand_conditional_type(&mut self, span: Span, ty: Type) -> Type
sourcepub(crate) fn get_index_signature(
&mut self,
span: Span,
ty: &Type
) -> VResult<Option<IndexSignature>>
pub(crate) fn get_index_signature(
&mut self,
span: Span,
ty: &Type
) -> VResult<Option<IndexSignature>>
Get IndexSignature from ty
, if there’s one.
pub(crate) fn get_index_signature_from_class(
&mut self,
span: Span,
class: &ClassDef
) -> VResult<Option<IndexSignature>>
sourcepub(crate) fn keyof(&mut self, span: Span, ty: &Type) -> VResult<Type>
pub(crate) fn keyof(&mut self, span: Span, ty: &Type) -> VResult<Type>
Evaluates keyof
operator.
Parameters
ty
Should be operand of keyof
.
Implementation note for Tuple
function f15<T extends string[], U extends T>(k0: keyof T, k1: keyof [...T], k2: keyof [...U], k3: keyof [1, 2, ...T]) {
k0 = 'length';
k1 = 'length';
k2 = 'length';
k0 = 'slice';
k1 = 'slice';
k2 = 'slice';
k3 = '0';
k3 = '1';
k3 = '2'; // Error
}
sourcepub(crate) fn expand_mapped(
&mut self,
span: Span,
m: &Mapped
) -> VResult<Option<Type>>
pub(crate) fn expand_mapped(
&mut self,
span: Span,
m: &Mapped
) -> VResult<Option<Type>>
Required because mapped type can specified by user, like
declare const a: Partial<Foo>;
TODO(kdy1): Handle index signatures.
fn expand_mapped_inner(&mut self, span: Span, m: &Mapped) -> VResult<Option<Type>>
fn expand_mapped_type_with_keyof(
&mut self,
span: Span,
keyof_operand: &Type,
original_keyof_operand: &Type,
m: &Mapped
) -> VResult<Option<Type>>
sourcefn expand_key_in_mapped(
&mut self,
mapped_type_param: Id,
mapped_ty: &Type,
key: &Key
) -> VResult<Type>
fn expand_key_in_mapped(
&mut self,
mapped_type_param: Id,
mapped_ty: &Type,
key: &Key
) -> VResult<Type>
TODO(kdy1): Optimize
sourcefn convert_type_to_keys_for_mapped_type(
&mut self,
span: Span,
ty: &Type,
name_type: Option<&Type>
) -> VResult<Option<Vec<Key>>>
fn convert_type_to_keys_for_mapped_type(
&mut self,
span: Span,
ty: &Type,
name_type: Option<&Type>
) -> VResult<Option<Vec<Key>>>
Evaluate a type and convert it to keys.
Used for types like 'foo' | 'bar'
or alias of them.
sourcepub(crate) fn get_property_names_for_mapped_type(
&mut self,
span: Span,
ty: &Type,
type_param: &TypeParam,
original_keyof_operand: &Type,
name_type: Option<&Type>
) -> VResult<Option<Vec<PropertyName>>>
pub(crate) fn get_property_names_for_mapped_type(
&mut self,
span: Span,
ty: &Type,
type_param: &TypeParam,
original_keyof_operand: &Type,
name_type: Option<&Type>
) -> VResult<Option<Vec<PropertyName>>>
Get keys of ty
as a property name.
pub(crate) fn apply_mapped_flags_to_type(
&mut self,
span: Span,
ty: Type,
optional: Option<TruePlusMinus>,
readonly: Option<TruePlusMinus>
) -> VResult<Type>
pub(crate) fn narrowed_type_of_assignment(
&mut self,
span: Span,
declared: Type,
actual: &Type
) -> VResult<Type>
pub(crate) fn add_required_type_params(&self, ty: &mut Type)
sourcepub(crate) fn normalize<'a>(
&mut self,
span: Option<Span>,
ty: Cow<'a, Type>,
opts: NormalizeTypeOpts
) -> VResult<Cow<'a, Type>>
pub(crate) fn normalize<'a>(
&mut self,
span: Option<Span>,
ty: Cow<'a, Type>,
opts: NormalizeTypeOpts
) -> VResult<Cow<'a, Type>>
This methods normalizes a type.
Changed types.
Span
If span
is provided, it will be used for types created by the
method. Otherwise the span of the original type is used.
fn reduce_conditional_type(
&mut self,
span: Span,
check_type: &Type,
check_type_constraint: &Type,
extends_type: &Type,
true_type: &Type,
false_type: &Type,
metadata: ConditionalMetadata
) -> VResult<Option<Type>>
pub(crate) fn normalize_intersection_types(
&mut self,
span: Span,
types: &[Type],
opts: NormalizeTypeOpts
) -> VResult<Option<Type>>
fn normalize_intersection_of_type_elements(
&mut self,
span: Span,
elements: &[TypeElement],
property_types: &mut Vec<TypeElement>,
opts: NormalizeTypeOpts
) -> VResult<Option<Type>>
fn instantiate_for_normalization(
&mut self,
span: Option<Span>,
ty: &Type,
opts: NormalizeTypeOpts
) -> VResult<Type>
pub(crate) fn report_possibly_null_or_undefined(
&mut self,
span: Span,
ty: &Type
) -> VResult<()>
pub(crate) fn can_be_undefined(
&mut self,
span: Span,
ty: &Type,
include_null: bool
) -> VResult<bool>
pub(crate) fn expand_type_ann<'a>(
&mut self,
span: Span,
ty: Option<&'a Type>
) -> VResult<Option<Cow<'a, Type>>>
pub(crate) fn create_prototype_of_class_def(
&mut self,
def: &ClassDef
) -> VResult<TypeLit>
sourcepub(crate) fn exclude_types_using_fact(
&mut self,
span: Span,
name: &Name,
ty: &mut Type
)
pub(crate) fn exclude_types_using_fact(
&mut self,
span: Span,
name: &Name,
ty: &mut Type
)
Exclude types from ty
using type facts with key name
, for
the current scope.
pub(crate) fn apply_type_facts(&mut self, name: &Name, ty: Type) -> Type
sourcepub(crate) fn collect_class_members(
&mut self,
excluded: &[&ClassMember],
ty: &Type
) -> VResult<Option<Vec<ClassMember>>>
pub(crate) fn collect_class_members(
&mut self,
excluded: &[&ClassMember],
ty: &Type
) -> VResult<Option<Vec<ClassMember>>>
sourcepub(crate) fn convert_type_to_type_lit<'a>(
&mut self,
span: Span,
ty: Cow<'a, Type>
) -> VResult<Option<Cow<'a, TypeLit>>>
pub(crate) fn convert_type_to_type_lit<'a>(
&mut self,
span: Span,
ty: Cow<'a, Type>
) -> VResult<Option<Cow<'a, TypeLit>>>
Note: span
is only used while expanding type (to prevent
panic) in the case of Type::Ref.
fn merge_type_elements(
&mut self,
span: Span,
els: Vec<TypeElement>
) -> VResult<Vec<TypeElement>>
fn merge_type_element(
&mut self,
span: Span,
to: &mut TypeElement,
from: TypeElement
) -> VResult<()>
pub(crate) fn normalize_tuples(&mut self, ty: &mut Type)
sourcepub(crate) fn kinds_of_type_elements(&mut self, els: &[TypeElement]) -> Vec<u8>ⓘNotable traits for Vec<u8, A>impl<A> Write for Vec<u8, A>where
A: Allocator,
pub(crate) fn kinds_of_type_elements(&mut self, els: &[TypeElement]) -> Vec<u8>ⓘNotable traits for Vec<u8, A>impl<A> Write for Vec<u8, A>where
A: Allocator,
A: Allocator,
This is used to determine form
of els
. Each type has a
value. e.g. 1
for TypeElement::Call.
pub(crate) fn expand_intrinsic_types(
&mut self,
span: Span,
ty: &StringMapping
) -> VResult<Type>
pub(crate) fn report_error_for_unresolved_type(
&mut self,
span: Span,
type_name: &RExpr,
type_args: Option<&TypeParamInstantiation>
) -> VResult<()>
sourcepub(super) fn make_type_el_from_class_member(
&self,
member: &ClassMember,
static_mode: bool
) -> Option<TypeElement>
pub(super) fn make_type_el_from_class_member(
&self,
member: &ClassMember,
static_mode: bool
) -> Option<TypeElement>
Utility method to convert a class member to a type element.
This method is used while inferring types and while assigning type element to class member or vice versa.
sourcefn exclude_type(&mut self, span: Span, ty: &mut Type, excluded: &Type)
fn exclude_type(&mut self, span: Span, ty: &mut Type, excluded: &Type)
Exclude excluded
from ty
Subclasses
class B {}
class P {}
class C extends P {}
declare let a: C | B
if (!(a instanceof P)) {
// At here, we can deduce that `a` is `B`.
// To use the fact that `a` is not `P`, we check for the parent type of `ty
}
fn exclude_types(&mut self, span: Span, ty: &mut Type, excludes: Option<Vec<Type>>)
sourcepub(crate) fn fill_known_type_names<N>(&mut self, node: &N)where
N: Send + Sync + for<'aa> VisitWith<BindingCollector<'aa>> + VisitWith<KnownTypeVisitor>,
pub(crate) fn fill_known_type_names<N>(&mut self, node: &N)where
N: Send + Sync + for<'aa> VisitWith<BindingCollector<'aa>> + VisitWith<KnownTypeVisitor>,
We precompute all type declarations in the scope, using this method.
sourcepub(crate) fn dump_type(&mut self, span: Span, ty: &Type)
pub(crate) fn dump_type(&mut self, span: Span, ty: &Type)
Prints type for visualization testing.
sourcefn make_instance_from_type_elements(
&mut self,
span: Span,
callee: &Type,
elements: &[TypeElement]
) -> VResult<Type>
fn make_instance_from_type_elements(
&mut self,
span: Span,
callee: &Type,
elements: &[TypeElement]
) -> VResult<Type>
span
and callee
is used only for error reporting.
sourcepub(super) fn make_instance_or_report(&mut self, span: Span, ty: &Type) -> Type
pub(super) fn make_instance_or_report(&mut self, span: Span, ty: &Type) -> Type
Make instance of ty
. In case of error, error will be reported to user
and ty
will be returned.
TODO(kdy1): Use Cow
fn new(&'b self, scope: Scope<'scope>, data: Box<AnalyzerData>) -> Self
pub(crate) fn with<F, Ret>(&mut self, op: F) -> Retwhere
F: for<'aa, 'bb> FnOnce(&mut Analyzer<'aa, 'bb>) -> Ret,
pub(crate) fn with_scope_for_type_params<F, Ret>(&mut self, op: F) -> Retwhere
F: for<'aa, 'bb> FnOnce(&mut Analyzer<'aa, 'bb>) -> Ret,
pub(crate) fn with_child<F, Ret>(
&mut self,
kind: ScopeKind,
facts: CondFacts,
op: F
) -> VResult<Ret>where
F: for<'aa, 'bb> FnOnce(&mut Analyzer<'aa, 'bb>) -> VResult<Ret>,
sourcepub(crate) fn with_child_with_hook<F, Ret, H>(
&mut self,
kind: ScopeKind,
facts: CondFacts,
op: F,
hook: H
) -> VResult<Ret>where
F: for<'aa, 'bb> FnOnce(&mut Analyzer<'aa, 'bb>) -> VResult<Ret>,
H: for<'aa, 'bb> FnOnce(&mut Analyzer<'aa, 'bb>),
pub(crate) fn with_child_with_hook<F, Ret, H>(
&mut self,
kind: ScopeKind,
facts: CondFacts,
op: F,
hook: H
) -> VResult<Ret>where
F: for<'aa, 'bb> FnOnce(&mut Analyzer<'aa, 'bb>) -> VResult<Ret>,
H: for<'aa, 'bb> FnOnce(&mut Analyzer<'aa, 'bb>),
Hook is invoked with self
(not child) after op
.
sourcefn line_col(&self, span: Span) -> String
fn line_col(&self, span: Span) -> String
Used for debugging. Returns the line and column of span.lo
in form of
(line, column)
.