@@ -24,8 +24,8 @@ namespace ts.codefix {
24
24
error : string
25
25
} ;
26
26
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 ) ;
29
29
if ( ! fieldInfo || ! fieldInfo . info ) return undefined ;
30
30
31
31
const changeTracker = textChanges . ChangeTracker . fromContext ( context ) ;
@@ -51,7 +51,7 @@ namespace ts.codefix {
51
51
}
52
52
}
53
53
54
- updateFieldDeclaration ( changeTracker , file , declaration , fieldName , fieldModifiers ) ;
54
+ updateFieldDeclaration ( changeTracker , file , declaration , type , fieldName , fieldModifiers ) ;
55
55
56
56
const getAccessor = generateGetAccessor ( fieldName , accessorName , type , accessorModifiers , isStatic , container ) ;
57
57
suppressLeadingAndTrailingTrivia ( getAccessor ) ;
@@ -112,7 +112,7 @@ namespace ts.codefix {
112
112
return modifierFlags ;
113
113
}
114
114
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 {
116
116
const node = getTokenAtPosition ( file , start ) ;
117
117
const cursorRequest = start === end && considerEmptySpans ;
118
118
const declaration = findAncestor ( node . parent , isAcceptedDeclaration ) ;
@@ -145,7 +145,7 @@ namespace ts.codefix {
145
145
info : {
146
146
isStatic : hasStaticModifier ( declaration ) ,
147
147
isReadonly : hasEffectiveReadonlyModifier ( declaration ) ,
148
- type : getTypeAnnotationNode ( declaration ) ,
148
+ type : getDeclarationType ( declaration , program ) ,
149
149
container : declaration . kind === SyntaxKind . Parameter ? declaration . parent . parent : declaration . parent ,
150
150
originalName : ( < AcceptedNameType > declaration . name ) . text ,
151
151
declaration,
@@ -195,14 +195,14 @@ namespace ts.codefix {
195
195
) ;
196
196
}
197
197
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 ) {
199
199
const property = factory . updatePropertyDeclaration (
200
200
declaration ,
201
201
declaration . decorators ,
202
202
modifiers ,
203
203
fieldName ,
204
204
declaration . questionToken || declaration . exclamationToken ,
205
- declaration . type ,
205
+ type ,
206
206
declaration . initializer
207
207
) ;
208
208
changeTracker . replaceNode ( file , declaration , property ) ;
@@ -213,9 +213,9 @@ namespace ts.codefix {
213
213
changeTracker . replacePropertyAssignment ( file , declaration , assignment ) ;
214
214
}
215
215
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 ) {
217
217
if ( isPropertyDeclaration ( declaration ) ) {
218
- updatePropertyDeclaration ( changeTracker , file , declaration , fieldName , modifiers ) ;
218
+ updatePropertyDeclaration ( changeTracker , file , declaration , type , fieldName , modifiers ) ;
219
219
}
220
220
else if ( isPropertyAssignment ( declaration ) ) {
221
221
updatePropertyAssignmentDeclaration ( changeTracker , file , declaration , fieldName ) ;
@@ -251,6 +251,19 @@ namespace ts.codefix {
251
251
} ) ;
252
252
}
253
253
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
+
254
267
export function getAllSupers ( decl : ClassOrInterface | undefined , checker : TypeChecker ) : readonly ClassOrInterface [ ] {
255
268
const res : ClassLikeDeclaration [ ] = [ ] ;
256
269
while ( decl ) {
0 commit comments