@@ -1555,12 +1555,15 @@ namespace ts {
1555
1555
return false ;
1556
1556
}
1557
1557
1558
+ type SerializedEntityNameAsExpression = Identifier | BinaryExpression | PropertyAccessExpression ;
1559
+ type SerializedTypeNode = SerializedEntityNameAsExpression | VoidExpression | ConditionalExpression ;
1560
+
1558
1561
/**
1559
1562
* Serializes the type of a node for use with decorator type metadata.
1560
1563
*
1561
1564
* @param node The node that should have its type serialized.
1562
1565
*/
1563
- function serializeTypeOfNode ( node : Node ) : Expression {
1566
+ function serializeTypeOfNode ( node : Node ) : SerializedTypeNode {
1564
1567
switch ( node . kind ) {
1565
1568
case SyntaxKind . PropertyDeclaration :
1566
1569
case SyntaxKind . Parameter :
@@ -1582,15 +1585,15 @@ namespace ts {
1582
1585
*
1583
1586
* @param node The node that should have its parameter types serialized.
1584
1587
*/
1585
- function serializeParameterTypesOfNode ( node : Node , container : ClassLikeDeclaration ) : Expression {
1588
+ function serializeParameterTypesOfNode ( node : Node , container : ClassLikeDeclaration ) : ArrayLiteralExpression {
1586
1589
const valueDeclaration =
1587
1590
isClassLike ( node )
1588
1591
? getFirstConstructorWithBody ( node )
1589
1592
: isFunctionLike ( node ) && nodeIsPresent ( node . body )
1590
1593
? node
1591
1594
: undefined ;
1592
1595
1593
- const expressions : Expression [ ] = [ ] ;
1596
+ const expressions : SerializedTypeNode [ ] = [ ] ;
1594
1597
if ( valueDeclaration ) {
1595
1598
const parameters = getParametersOfDecoratedDeclaration ( valueDeclaration , container ) ;
1596
1599
const numParameters = parameters . length ;
@@ -1626,7 +1629,7 @@ namespace ts {
1626
1629
*
1627
1630
* @param node The node that should have its return type serialized.
1628
1631
*/
1629
- function serializeReturnTypeOfNode ( node : Node ) : Expression {
1632
+ function serializeReturnTypeOfNode ( node : Node ) : SerializedTypeNode {
1630
1633
if ( isFunctionLike ( node ) && node . type ) {
1631
1634
return serializeTypeNode ( node . type ) ;
1632
1635
}
@@ -1655,13 +1658,16 @@ namespace ts {
1655
1658
*
1656
1659
* @param node The type node to serialize.
1657
1660
*/
1658
- function serializeTypeNode ( node : TypeNode ) : Expression {
1661
+ function serializeTypeNode ( node : TypeNode ) : SerializedTypeNode {
1659
1662
if ( node === undefined ) {
1660
1663
return createIdentifier ( "Object" ) ;
1661
1664
}
1662
1665
1663
1666
switch ( node . kind ) {
1664
1667
case SyntaxKind . VoidKeyword :
1668
+ case SyntaxKind . UndefinedKeyword :
1669
+ case SyntaxKind . NullKeyword :
1670
+ case SyntaxKind . NeverKeyword :
1665
1671
return createVoidZero ( ) ;
1666
1672
1667
1673
case SyntaxKind . ParenthesizedType :
@@ -1713,37 +1719,8 @@ namespace ts {
1713
1719
1714
1720
case SyntaxKind . IntersectionType :
1715
1721
case SyntaxKind . UnionType :
1716
- {
1717
- const unionOrIntersection = < UnionOrIntersectionTypeNode > node ;
1718
- let serializedUnion : Identifier ;
1719
- for ( const typeNode of unionOrIntersection . types ) {
1720
- const serializedIndividual = serializeTypeNode ( typeNode ) as Identifier ;
1721
- // Non identifier
1722
- if ( serializedIndividual . kind !== SyntaxKind . Identifier ) {
1723
- serializedUnion = undefined ;
1724
- break ;
1725
- }
1726
-
1727
- // One of the individual is global object, return immediately
1728
- if ( serializedIndividual . text === "Object" ) {
1729
- return serializedIndividual ;
1730
- }
1731
-
1732
- // Different types
1733
- if ( serializedUnion && serializedUnion . text !== serializedIndividual . text ) {
1734
- serializedUnion = undefined ;
1735
- break ;
1736
- }
1737
-
1738
- serializedUnion = serializedIndividual ;
1739
- }
1722
+ return serializeUnionOrIntersectionType ( < UnionOrIntersectionTypeNode > node ) ;
1740
1723
1741
- // If we were able to find common type
1742
- if ( serializedUnion ) {
1743
- return serializedUnion ;
1744
- }
1745
- }
1746
- // Fallthrough
1747
1724
case SyntaxKind . TypeQuery :
1748
1725
case SyntaxKind . TypeOperator :
1749
1726
case SyntaxKind . IndexedAccessType :
@@ -1761,13 +1738,48 @@ namespace ts {
1761
1738
return createIdentifier ( "Object" ) ;
1762
1739
}
1763
1740
1741
+ function serializeUnionOrIntersectionType ( node : UnionOrIntersectionTypeNode ) : SerializedTypeNode {
1742
+ let serializedUnion : SerializedTypeNode ;
1743
+ for ( const typeNode of node . types ) {
1744
+ const serializedIndividual = serializeTypeNode ( typeNode ) ;
1745
+
1746
+ if ( isVoidExpression ( serializedIndividual ) ) {
1747
+ // If we dont have any other type already set, set the initial type
1748
+ if ( ! serializedUnion ) {
1749
+ serializedUnion = serializedIndividual ;
1750
+ }
1751
+ }
1752
+ else if ( isIdentifier ( serializedIndividual ) && serializedIndividual . text === "Object" ) {
1753
+ // One of the individual is global object, return immediately
1754
+ return serializedIndividual ;
1755
+ }
1756
+ // If there exists union that is not void 0 expression, check if the the common type is identifier.
1757
+ // anything more complex and we will just default to Object
1758
+ else if ( serializedUnion && ! isVoidExpression ( serializedUnion ) ) {
1759
+ // Different types
1760
+ if ( ! isIdentifier ( serializedUnion ) ||
1761
+ ! isIdentifier ( serializedIndividual ) ||
1762
+ serializedUnion . text !== serializedIndividual . text ) {
1763
+ return createIdentifier ( "Object" ) ;
1764
+ }
1765
+ }
1766
+ else {
1767
+ // Initialize the union type
1768
+ serializedUnion = serializedIndividual ;
1769
+ }
1770
+ }
1771
+
1772
+ // If we were able to find common type, use it
1773
+ return serializedUnion ;
1774
+ }
1775
+
1764
1776
/**
1765
1777
* Serializes a TypeReferenceNode to an appropriate JS constructor value for use with
1766
1778
* decorator type metadata.
1767
1779
*
1768
1780
* @param node The type reference node.
1769
1781
*/
1770
- function serializeTypeReferenceNode ( node : TypeReferenceNode ) {
1782
+ function serializeTypeReferenceNode ( node : TypeReferenceNode ) : SerializedTypeNode {
1771
1783
switch ( resolver . getTypeReferenceSerializationKind ( node . typeName , currentScope ) ) {
1772
1784
case TypeReferenceSerializationKind . Unknown :
1773
1785
const serialized = serializeEntityNameAsExpression ( node . typeName , /*useFallback*/ true ) ;
@@ -1822,7 +1834,7 @@ namespace ts {
1822
1834
* @param useFallback A value indicating whether to use logical operators to test for the
1823
1835
* entity name at runtime.
1824
1836
*/
1825
- function serializeEntityNameAsExpression ( node : EntityName , useFallback : boolean ) : Expression {
1837
+ function serializeEntityNameAsExpression ( node : EntityName , useFallback : boolean ) : SerializedEntityNameAsExpression {
1826
1838
switch ( node . kind ) {
1827
1839
case SyntaxKind . Identifier :
1828
1840
// Create a clone of the name with a new parent, and treat it as if it were
@@ -1855,8 +1867,8 @@ namespace ts {
1855
1867
* @param useFallback A value indicating whether to use logical operators to test for the
1856
1868
* qualified name at runtime.
1857
1869
*/
1858
- function serializeQualifiedNameAsExpression ( node : QualifiedName , useFallback : boolean ) : Expression {
1859
- let left : Expression ;
1870
+ function serializeQualifiedNameAsExpression ( node : QualifiedName , useFallback : boolean ) : PropertyAccessExpression {
1871
+ let left : SerializedEntityNameAsExpression ;
1860
1872
if ( node . left . kind === SyntaxKind . Identifier ) {
1861
1873
left = serializeEntityNameAsExpression ( node . left , useFallback ) ;
1862
1874
}
@@ -1881,7 +1893,7 @@ namespace ts {
1881
1893
* Gets an expression that points to the global "Symbol" constructor at runtime if it is
1882
1894
* available.
1883
1895
*/
1884
- function getGlobalSymbolNameWithFallback ( ) : Expression {
1896
+ function getGlobalSymbolNameWithFallback ( ) : ConditionalExpression {
1885
1897
return createConditional (
1886
1898
createTypeCheck ( createIdentifier ( "Symbol" ) , "function" ) ,
1887
1899
createIdentifier ( "Symbol" ) ,
0 commit comments