Address comment: call getContextualType instead of accessing contextualType property directly

This commit is contained in:
Kanchalai Tanglertsampan 2016-11-14 11:19:26 -08:00
parent 2fd5667a04
commit 350f47aa3a
4 changed files with 16 additions and 25 deletions

View File

@ -7600,7 +7600,7 @@ namespace ts {
return true;
}
else if (getPropertyOfType(type, name) || (isComparingJsxAttributes && !isUnhyphenatedJsxName(name))) {
// For JSXAttributes, if the attribute has hyphenated name considered the attribute to be known
// For JSXAttributes, if the attribute has a hyphenated name, consider that the attribute to be known.
return true;
}
}
@ -11281,27 +11281,19 @@ namespace ts {
function getContextualTypeForJsxAttribute(attribute: JsxAttribute | JsxSpreadAttribute) {
// When we trying to resolve JsxOpeningLikeElement as a stateless function element, we will already give JSXAttributes a contextual type
// which is a type of the parameter of the signature we are trying out. This is not the case if it is a statefull Jsx (i.e ReactComponenet class)
// which is a type of the parameter of the signature we are trying out. This is not the case if it is a stateful JSX (i.e ReactComponenet class)
// So if that is the case, just return the type of the JsxAttribute in such contextual type with out going into resolving of the JsxOpeningLikeElement again
if ((<JsxAttributes>attribute.parent).contextualType) {
return isJsxAttribute(attribute) ? getTypeOfPropertyOfType((<JsxAttributes>attribute.parent).contextualType, attribute.name.text) : undefined;
}
const attributesType = getContextualType(<Expression>attribute.parent) || getAttributesTypeFromJsxOpeningLikeElement(<JsxOpeningLikeElement>attribute.parent.parent);
const kind = attribute.kind;
const jsxElement = attribute.parent.parent as JsxOpeningLikeElement;
const attrsType = getAttributesTypeFromJsxOpeningLikeElement(jsxElement);
if (kind === SyntaxKind.JsxAttribute) {
if (!attrsType || isTypeAny(attrsType)) {
if (isJsxAttribute(attribute)) {
if (!attributesType || isTypeAny(attributesType)) {
return undefined;
}
return getTypeOfPropertyOfType(attrsType, (attribute as JsxAttribute).name.text);
return getTypeOfPropertyOfType(attributesType, (attribute as JsxAttribute).name.text);
}
else if (kind === SyntaxKind.JsxSpreadAttribute) {
return attrsType;
else {
return attributesType;
}
Debug.fail(`Expected JsxAttribute or JsxSpreadAttribute, got ts.SyntaxKind[${kind}]`);
}
// Return the contextual type for a given expression node. During overload resolution, a contextual type may temporarily
@ -11992,7 +11984,7 @@ namespace ts {
let sourceAttributesType = anyType as Type;
let isSourceAttributesTypeEmpty = true;
if (symbolArray) {
// Filter out any hyphenated names as those are not play any role in type-checking unless there are corresponding properties in the target type
// Filter out any hyphenated names as those do not play any role in type-checking unless there are corresponding properties in the target type
const symbolTable = createMap<Symbol>();
forEach(symbolArray, (attr) => {
if (isUnhyphenatedJsxName(attr.name) || getPropertyOfType(targetAttributesType, attr.name)) {

View File

@ -1507,14 +1507,13 @@
attributes: JsxAttributes;
}
// @kind(SyntaxKind.JsxAttribute)
export interface JsxAttribute extends ObjectLiteralElement {
kind: SyntaxKind.JsxAttribute;
name: Identifier;
/// JSX attribute initializers are optional; <X y /> is sugar for <X y={true} />
initializer?: StringLiteral | JsxExpression;
}
// @kind(SyntaxKind.JsxSpreadAttribute)
export interface JsxSpreadAttribute extends ObjectLiteralElement {
kind: SyntaxKind.JsxSpreadAttribute;
expression: Expression;

View File

@ -1,4 +1,4 @@
tests/cases/conformance/types/contextualTypes/jsxAttributes/file.tsx(28,24): error TS2322: Type '{ extra: true; onClick: (k: any) => void; }' is not assignable to type 'IntrinsicAttributes & LinkProps'.
tests/cases/conformance/types/contextualTypes/jsxAttributes/file.tsx(28,24): error TS2322: Type '{ extra: true; onClick: (k: "left" | "right") => void; }' is not assignable to type 'IntrinsicAttributes & LinkProps'.
Property 'extra' does not exist on type 'IntrinsicAttributes & LinkProps'.
tests/cases/conformance/types/contextualTypes/jsxAttributes/file.tsx(29,24): error TS2322: Type '{ onClick: (k: "left" | "right") => void; extra: true; }' is not assignable to type 'IntrinsicAttributes & LinkProps'.
Property 'onClick' does not exist on type 'IntrinsicAttributes & LinkProps'.
@ -6,7 +6,7 @@ tests/cases/conformance/types/contextualTypes/jsxAttributes/file.tsx(30,24): err
Property 'extra' does not exist on type 'IntrinsicAttributes & LinkProps'.
tests/cases/conformance/types/contextualTypes/jsxAttributes/file.tsx(31,24): error TS2322: Type '{ goTo: "home"; extra: true; }' is not assignable to type 'IntrinsicAttributes & LinkProps'.
Property 'extra' does not exist on type 'IntrinsicAttributes & LinkProps'.
tests/cases/conformance/types/contextualTypes/jsxAttributes/file.tsx(34,25): error TS2322: Type '{ extra: true; onClick: (k: any) => void; }' is not assignable to type 'IntrinsicAttributes & ButtonProps'.
tests/cases/conformance/types/contextualTypes/jsxAttributes/file.tsx(34,25): error TS2322: Type '{ extra: true; onClick: (k: "left" | "right") => void; }' is not assignable to type 'IntrinsicAttributes & ButtonProps'.
Property 'extra' does not exist on type 'IntrinsicAttributes & ButtonProps'.
tests/cases/conformance/types/contextualTypes/jsxAttributes/file.tsx(37,25): error TS2322: Type '{ extra: true; goTo: "home"; }' is not assignable to type 'IntrinsicAttributes & LinkProps'.
Property 'extra' does not exist on type 'IntrinsicAttributes & LinkProps'.
@ -42,7 +42,7 @@ tests/cases/conformance/types/contextualTypes/jsxAttributes/file.tsx(37,25): err
const b0 = <MainButton {...{onClick: (k) => {console.log(k)}}} extra />; // k has type any
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2322: Type '{ extra: true; onClick: (k: any) => void; }' is not assignable to type 'IntrinsicAttributes & LinkProps'.
!!! error TS2322: Type '{ extra: true; onClick: (k: "left" | "right") => void; }' is not assignable to type 'IntrinsicAttributes & LinkProps'.
!!! error TS2322: Property 'extra' does not exist on type 'IntrinsicAttributes & LinkProps'.
const b2 = <MainButton onClick={(k)=>{console.log(k)}} extra />; // k has type "left" | "right"
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -60,7 +60,7 @@ tests/cases/conformance/types/contextualTypes/jsxAttributes/file.tsx(37,25): err
export function NoOverload(buttonProps: ButtonProps): JSX.Element { return undefined }
const c1 = <NoOverload {...{onClick: (k) => {console.log(k)}}} extra />; // k has type any
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2322: Type '{ extra: true; onClick: (k: any) => void; }' is not assignable to type 'IntrinsicAttributes & ButtonProps'.
!!! error TS2322: Type '{ extra: true; onClick: (k: "left" | "right") => void; }' is not assignable to type 'IntrinsicAttributes & ButtonProps'.
!!! error TS2322: Property 'extra' does not exist on type 'IntrinsicAttributes & ButtonProps'.
export function NoOverload1(linkProps: LinkProps): JSX.Element { return undefined }

View File

@ -4,7 +4,7 @@ tests/cases/conformance/jsx/file.tsx(50,24): error TS2322: Type '{ to: string; o
Property 'to' does not exist on type 'IntrinsicAttributes & HyphenProps'.
tests/cases/conformance/jsx/file.tsx(51,24): error TS2322: Type '{ onClick: () => void; to: string; }' is not assignable to type 'IntrinsicAttributes & HyphenProps'.
Property 'onClick' does not exist on type 'IntrinsicAttributes & HyphenProps'.
tests/cases/conformance/jsx/file.tsx(52,24): error TS2322: Type '{ onClick: (k: any) => void; to: string; }' is not assignable to type 'IntrinsicAttributes & HyphenProps'.
tests/cases/conformance/jsx/file.tsx(52,24): error TS2322: Type '{ onClick: (k: MouseEvent<any>) => void; to: string; }' is not assignable to type 'IntrinsicAttributes & HyphenProps'.
Property 'onClick' does not exist on type 'IntrinsicAttributes & HyphenProps'.
tests/cases/conformance/jsx/file.tsx(54,24): error TS2322: Type '{ to: string; onClick(e: any): void; }' is not assignable to type 'IntrinsicAttributes & HyphenProps'.
Property 'to' does not exist on type 'IntrinsicAttributes & HyphenProps'.
@ -81,7 +81,7 @@ tests/cases/conformance/jsx/file.tsx(57,24): error TS2322: Type '{ data-format:
!!! error TS2322: Property 'onClick' does not exist on type 'IntrinsicAttributes & HyphenProps'.
const b3 = <MainButton {...{to: "10000"}} {...{onClick: (k) => {}}} />; // extra property
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2322: Type '{ onClick: (k: any) => void; to: string; }' is not assignable to type 'IntrinsicAttributes & HyphenProps'.
!!! error TS2322: Type '{ onClick: (k: MouseEvent<any>) => void; to: string; }' is not assignable to type 'IntrinsicAttributes & HyphenProps'.
!!! error TS2322: Property 'onClick' does not exist on type 'IntrinsicAttributes & HyphenProps'.
const b4 = <MainButton {...obj3} to />; // Should error because Incorrect type; but attributes are any so everything is allowed
const b5 = <MainButton {...{ onClick(e: any) { } }} {...obj0} />; // Spread retain method declaration (see GitHub #13365), so now there is an extra attributes