@@ -1637,6 +1637,8 @@ namespace ts {
1637
1637
return createVoidZero ( ) ;
1638
1638
}
1639
1639
1640
+ type SerializedTypeNode = SerializedEntityNameAsExpression | VoidExpression | ConditionalExpression ;
1641
+
1640
1642
/**
1641
1643
* Serializes a type node for use with decorator type metadata.
1642
1644
*
@@ -1655,7 +1657,7 @@ namespace ts {
1655
1657
*
1656
1658
* @param node The type node to serialize.
1657
1659
*/
1658
- function serializeTypeNode ( node : TypeNode ) : Expression {
1660
+ function serializeTypeNode ( node : TypeNode ) : SerializedTypeNode {
1659
1661
if ( node === undefined ) {
1660
1662
return createIdentifier ( "Object" ) ;
1661
1663
}
@@ -1664,6 +1666,7 @@ namespace ts {
1664
1666
case SyntaxKind . VoidKeyword :
1665
1667
case SyntaxKind . UndefinedKeyword :
1666
1668
case SyntaxKind . NullKeyword :
1669
+ case SyntaxKind . NeverKeyword :
1667
1670
return createVoidZero ( ) ;
1668
1671
1669
1672
case SyntaxKind . ParenthesizedType :
@@ -1715,53 +1718,15 @@ namespace ts {
1715
1718
1716
1719
case SyntaxKind . IntersectionType :
1717
1720
case SyntaxKind . UnionType :
1718
- {
1719
- const unionOrIntersection = < UnionOrIntersectionTypeNode > node ;
1720
- let serializedUnion : Identifier | VoidExpression ;
1721
- for ( const typeNode of unionOrIntersection . types ) {
1722
- const serializedIndividual = serializeTypeNode ( typeNode ) ;
1723
-
1724
- if ( isIdentifier ( serializedIndividual ) ) {
1725
- // One of the individual is global object, return immediately
1726
- if ( serializedIndividual . text === "Object" ) {
1727
- return serializedIndividual ;
1728
- }
1729
-
1730
- // Different types
1731
- if ( serializedUnion && isIdentifier ( serializedUnion ) && serializedUnion . text !== serializedIndividual . text ) {
1732
- serializedUnion = undefined ;
1733
- break ;
1734
- }
1735
-
1736
- serializedUnion = serializedIndividual ;
1737
- }
1738
- else if ( isVoidExpression ( serializedIndividual ) ) {
1739
- // If we dont have any other type already set, set the initial type
1740
- if ( ! serializedUnion ) {
1741
- serializedUnion = serializedIndividual ;
1742
- }
1743
- }
1744
- else {
1745
- // Non identifier and undefined/null
1746
- serializedUnion = undefined ;
1747
- break ;
1748
- }
1749
- }
1721
+ return serializeUnionOrIntersectionType ( < UnionOrIntersectionTypeNode > node ) ;
1750
1722
1751
- // If we were able to find common type
1752
- if ( serializedUnion ) {
1753
- return serializedUnion ;
1754
- }
1755
- }
1756
- // Fallthrough
1757
1723
case SyntaxKind . TypeQuery :
1758
1724
case SyntaxKind . TypeOperator :
1759
1725
case SyntaxKind . IndexedAccessType :
1760
1726
case SyntaxKind . MappedType :
1761
1727
case SyntaxKind . TypeLiteral :
1762
1728
case SyntaxKind . AnyKeyword :
1763
1729
case SyntaxKind . ThisType :
1764
- case SyntaxKind . NeverKeyword :
1765
1730
break ;
1766
1731
1767
1732
default :
@@ -1772,13 +1737,48 @@ namespace ts {
1772
1737
return createIdentifier ( "Object" ) ;
1773
1738
}
1774
1739
1740
+ function serializeUnionOrIntersectionType ( node : UnionOrIntersectionTypeNode ) : SerializedTypeNode {
1741
+ let serializedUnion : SerializedTypeNode ;
1742
+ for ( const typeNode of node . types ) {
1743
+ const serializedIndividual = serializeTypeNode ( typeNode ) ;
1744
+
1745
+ if ( isVoidExpression ( serializedIndividual ) ) {
1746
+ // If we dont have any other type already set, set the initial type
1747
+ if ( ! serializedUnion ) {
1748
+ serializedUnion = serializedIndividual ;
1749
+ }
1750
+ }
1751
+ else if ( isIdentifier ( serializedIndividual ) && serializedIndividual . text === "Object" ) {
1752
+ // One of the individual is global object, return immediately
1753
+ return serializedIndividual ;
1754
+ }
1755
+ // If there exists union that is not void 0 expression, check if the the common type is identifier.
1756
+ // anything more complex and we will just default to Object
1757
+ else if ( serializedUnion && ! isVoidExpression ( serializedUnion ) ) {
1758
+ // Different types
1759
+ if ( ! isIdentifier ( serializedUnion ) ||
1760
+ ! isIdentifier ( serializedIndividual ) ||
1761
+ serializedUnion . text !== serializedIndividual . text ) {
1762
+ return createIdentifier ( "Object" ) ;
1763
+ }
1764
+ }
1765
+ else {
1766
+ // Initialize the union type
1767
+ serializedUnion = serializedIndividual ;
1768
+ }
1769
+ }
1770
+
1771
+ // If we were able to find common type, use it
1772
+ return serializedUnion ;
1773
+ }
1774
+
1775
1775
/**
1776
1776
* Serializes a TypeReferenceNode to an appropriate JS constructor value for use with
1777
1777
* decorator type metadata.
1778
1778
*
1779
1779
* @param node The type reference node.
1780
1780
*/
1781
- function serializeTypeReferenceNode ( node : TypeReferenceNode ) {
1781
+ function serializeTypeReferenceNode ( node : TypeReferenceNode ) : SerializedTypeNode {
1782
1782
switch ( resolver . getTypeReferenceSerializationKind ( node . typeName , currentScope ) ) {
1783
1783
case TypeReferenceSerializationKind . Unknown :
1784
1784
const serialized = serializeEntityNameAsExpression ( node . typeName , /*useFallback*/ true ) ;
@@ -1826,14 +1826,15 @@ namespace ts {
1826
1826
}
1827
1827
}
1828
1828
1829
+ type SerializedEntityNameAsExpression = Identifier | BinaryExpression | PropertyAccessExpression ;
1829
1830
/**
1830
1831
* Serializes an entity name as an expression for decorator type metadata.
1831
1832
*
1832
1833
* @param node The entity name to serialize.
1833
1834
* @param useFallback A value indicating whether to use logical operators to test for the
1834
1835
* entity name at runtime.
1835
1836
*/
1836
- function serializeEntityNameAsExpression ( node : EntityName , useFallback : boolean ) : Expression {
1837
+ function serializeEntityNameAsExpression ( node : EntityName , useFallback : boolean ) : SerializedEntityNameAsExpression {
1837
1838
switch ( node . kind ) {
1838
1839
case SyntaxKind . Identifier :
1839
1840
// Create a clone of the name with a new parent, and treat it as if it were
@@ -1866,8 +1867,8 @@ namespace ts {
1866
1867
* @param useFallback A value indicating whether to use logical operators to test for the
1867
1868
* qualified name at runtime.
1868
1869
*/
1869
- function serializeQualifiedNameAsExpression ( node : QualifiedName , useFallback : boolean ) : Expression {
1870
- let left : Expression ;
1870
+ function serializeQualifiedNameAsExpression ( node : QualifiedName , useFallback : boolean ) : PropertyAccessExpression {
1871
+ let left : SerializedEntityNameAsExpression ;
1871
1872
if ( node . left . kind === SyntaxKind . Identifier ) {
1872
1873
left = serializeEntityNameAsExpression ( node . left , useFallback ) ;
1873
1874
}
@@ -1892,7 +1893,7 @@ namespace ts {
1892
1893
* Gets an expression that points to the global "Symbol" constructor at runtime if it is
1893
1894
* available.
1894
1895
*/
1895
- function getGlobalSymbolNameWithFallback ( ) : Expression {
1896
+ function getGlobalSymbolNameWithFallback ( ) : ConditionalExpression {
1896
1897
return createConditional (
1897
1898
createTypeCheck ( createIdentifier ( "Symbol" ) , "function" ) ,
1898
1899
createIdentifier ( "Symbol" ) ,
0 commit comments