@@ -24,8 +24,8 @@ namespace ts.codefix {
2424 error : string
2525 } ;
2626
27- export function generateAccessorFromProperty ( file : SourceFile , start : number , end : number , context : textChanges . TextChangesContext , _actionName : string ) : FileTextChanges [ ] | undefined {
28- const fieldInfo = getAccessorConvertiblePropertyAtPosition ( file , start , end ) ;
27+ export function generateAccessorFromProperty ( file : SourceFile , program : Program , start : number , end : number , context : textChanges . TextChangesContext , _actionName : string ) : FileTextChanges [ ] | undefined {
28+ const fieldInfo = getAccessorConvertiblePropertyAtPosition ( file , program , start , end ) ;
2929 if ( ! fieldInfo || ! fieldInfo . info ) return undefined ;
3030
3131 const changeTracker = textChanges . ChangeTracker . fromContext ( context ) ;
@@ -51,7 +51,7 @@ namespace ts.codefix {
5151 }
5252 }
5353
54- updateFieldDeclaration ( changeTracker , file , declaration , fieldName , fieldModifiers ) ;
54+ updateFieldDeclaration ( changeTracker , file , declaration , type , fieldName , fieldModifiers ) ;
5555
5656 const getAccessor = generateGetAccessor ( fieldName , accessorName , type , accessorModifiers , isStatic , container ) ;
5757 suppressLeadingAndTrailingTrivia ( getAccessor ) ;
@@ -112,7 +112,7 @@ namespace ts.codefix {
112112 return modifierFlags ;
113113 }
114114
115- export function getAccessorConvertiblePropertyAtPosition ( file : SourceFile , start : number , end : number , considerEmptySpans = true ) : InfoOrError | undefined {
115+ export function getAccessorConvertiblePropertyAtPosition ( file : SourceFile , program : Program , start : number , end : number , considerEmptySpans = true ) : InfoOrError | undefined {
116116 const node = getTokenAtPosition ( file , start ) ;
117117 const cursorRequest = start === end && considerEmptySpans ;
118118 const declaration = findAncestor ( node . parent , isAcceptedDeclaration ) ;
@@ -145,7 +145,7 @@ namespace ts.codefix {
145145 info : {
146146 isStatic : hasStaticModifier ( declaration ) ,
147147 isReadonly : hasEffectiveReadonlyModifier ( declaration ) ,
148- type : getTypeAnnotationNode ( declaration ) ,
148+ type : getDeclarationType ( declaration , program ) ,
149149 container : declaration . kind === SyntaxKind . Parameter ? declaration . parent . parent : declaration . parent ,
150150 originalName : ( < AcceptedNameType > declaration . name ) . text ,
151151 declaration,
@@ -195,14 +195,14 @@ namespace ts.codefix {
195195 ) ;
196196 }
197197
198- function updatePropertyDeclaration ( changeTracker : textChanges . ChangeTracker , file : SourceFile , declaration : PropertyDeclaration , fieldName : AcceptedNameType , modifiers : ModifiersArray | undefined ) {
198+ function updatePropertyDeclaration ( changeTracker : textChanges . ChangeTracker , file : SourceFile , declaration : PropertyDeclaration , type : TypeNode | undefined , fieldName : AcceptedNameType , modifiers : ModifiersArray | undefined ) {
199199 const property = factory . updatePropertyDeclaration (
200200 declaration ,
201201 declaration . decorators ,
202202 modifiers ,
203203 fieldName ,
204204 declaration . questionToken || declaration . exclamationToken ,
205- declaration . type ,
205+ type ,
206206 declaration . initializer
207207 ) ;
208208 changeTracker . replaceNode ( file , declaration , property ) ;
@@ -213,9 +213,9 @@ namespace ts.codefix {
213213 changeTracker . replacePropertyAssignment ( file , declaration , assignment ) ;
214214 }
215215
216- function updateFieldDeclaration ( changeTracker : textChanges . ChangeTracker , file : SourceFile , declaration : AcceptedDeclaration , fieldName : AcceptedNameType , modifiers : ModifiersArray | undefined ) {
216+ function updateFieldDeclaration ( changeTracker : textChanges . ChangeTracker , file : SourceFile , declaration : AcceptedDeclaration , type : TypeNode | undefined , fieldName : AcceptedNameType , modifiers : ModifiersArray | undefined ) {
217217 if ( isPropertyDeclaration ( declaration ) ) {
218- updatePropertyDeclaration ( changeTracker , file , declaration , fieldName , modifiers ) ;
218+ updatePropertyDeclaration ( changeTracker , file , declaration , type , fieldName , modifiers ) ;
219219 }
220220 else if ( isPropertyAssignment ( declaration ) ) {
221221 updatePropertyAssignmentDeclaration ( changeTracker , file , declaration , fieldName ) ;
@@ -251,6 +251,19 @@ namespace ts.codefix {
251251 } ) ;
252252 }
253253
254+ function getDeclarationType ( declaration : AcceptedDeclaration , program : Program ) : TypeNode | undefined {
255+ const typeNode = getTypeAnnotationNode ( declaration ) ;
256+ if ( isPropertyDeclaration ( declaration ) && typeNode && declaration . questionToken ) {
257+ const typeChecker = program . getTypeChecker ( ) ;
258+ const type = typeChecker . getTypeFromTypeNode ( typeNode ) ;
259+ if ( ! typeChecker . isTypeAssignableTo ( typeChecker . getUndefinedType ( ) , type ) ) {
260+ const types = isUnionTypeNode ( typeNode ) ? typeNode . types : [ typeNode ] ;
261+ return factory . createUnionTypeNode ( [ ...types , factory . createKeywordTypeNode ( SyntaxKind . UndefinedKeyword ) ] ) ;
262+ }
263+ }
264+ return typeNode ;
265+ }
266+
254267 export function getAllSupers ( decl : ClassOrInterface | undefined , checker : TypeChecker ) : readonly ClassOrInterface [ ] {
255268 const res : ClassLikeDeclaration [ ] = [ ] ;
256269 while ( decl ) {
0 commit comments