@ttsc/lint 0.25.0 → 0.26.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -143,6 +143,34 @@ type functionalNoTryOptions struct {
143
143
  AllowFinally bool `json:"allowFinally"`
144
144
  }
145
145
 
146
+ // functionalNoMixedTypesOptions gates the two container kinds the rule visits.
147
+ // Both default to true (an absent key leaves the container checked), so the
148
+ // pointers distinguish "not configured" from an explicit false.
149
+ type functionalNoMixedTypesOptions struct {
150
+ CheckInterfaces *bool `json:"checkInterfaces"`
151
+ CheckTypeLiterals *bool `json:"checkTypeLiterals"`
152
+ }
153
+
154
+ // functionalNoReturnVoidOptions narrows what counts as a rejected return.
155
+ //
156
+ // `allowNull` and `allowUndefined` default to true, matching the rule's
157
+ // existing behavior: only a declared `void` return type is rejected. Setting
158
+ // either to false extends the rejection to that declared return type.
159
+ // `ignoreInferredTypes` defaults to false and, when true, spares a bare
160
+ // `return;` whose enclosing function declares no return type, which is the one
161
+ // place the rule reports a void-ness it inferred rather than read.
162
+ type functionalNoReturnVoidOptions struct {
163
+ AllowNull *bool `json:"allowNull"`
164
+ AllowUndefined *bool `json:"allowUndefined"`
165
+ IgnoreInferredTypes bool `json:"ignoreInferredTypes"`
166
+ }
167
+
168
+ // functionalPreferTacitOptions gates the member-expression callee shape.
169
+ // Defaults to true, keeping `x => service.handler(x)` reported as before.
170
+ type functionalPreferTacitOptions struct {
171
+ CheckMemberExpressions *bool `json:"checkMemberExpressions"`
172
+ }
173
+
146
174
  type functionalImmutableDataOptions struct {
147
175
  functionalPatternOptions
148
176
  IgnoreMapsAndSets bool `json:"ignoreMapsAndSets"`
@@ -159,8 +187,15 @@ type functionalPreferImmutableTypesOptions struct {
159
187
  functionalPatternOptions
160
188
  }
161
189
 
190
+ // functionalPreferReadonlyTypeOptions narrows which positions the rule polices.
191
+ // Both gates default to off, so an absent key leaves every visited position
192
+ // checked exactly as before.
162
193
  type functionalPreferReadonlyTypeOptions struct {
163
194
  functionalPatternOptions
195
+ AllowMutableReturnType bool `json:"allowMutableReturnType"`
196
+ IgnoreClass interface{} `json:"ignoreClass"`
197
+ IgnoreCollections bool `json:"ignoreCollections"`
198
+ IgnoreInterface bool `json:"ignoreInterface"`
164
199
  }
165
200
 
166
201
  type functionalReadonlyTypeOptions struct {
@@ -332,6 +367,18 @@ func (functionalNoLoopStatements) Check(ctx *Context, node *shimast.Node) {
332
367
  }
333
368
 
334
369
  func (functionalNoMixedTypes) Check(ctx *Context, node *shimast.Node) {
370
+ var opts functionalNoMixedTypesOptions
371
+ _ = ctx.DecodeOptions(&opts)
372
+ switch node.Kind {
373
+ case shimast.KindInterfaceDeclaration:
374
+ if opts.CheckInterfaces != nil && !*opts.CheckInterfaces {
375
+ return
376
+ }
377
+ case shimast.KindTypeLiteral:
378
+ if opts.CheckTypeLiterals != nil && !*opts.CheckTypeLiterals {
379
+ return
380
+ }
381
+ }
335
382
  members := containerMembers(node)
336
383
  if len(members) < 2 {
337
384
  return
@@ -361,16 +408,51 @@ func (functionalNoPromiseReject) Check(ctx *Context, node *shimast.Node) {
361
408
  }
362
409
 
363
410
  func (functionalNoReturnVoid) Check(ctx *Context, node *shimast.Node) {
411
+ var opts functionalNoReturnVoidOptions
412
+ _ = ctx.DecodeOptions(&opts)
364
413
  if node.Kind == shimast.KindReturnStatement {
365
414
  ret := node.AsReturnStatement()
366
- if ret != nil && ret.Expression == nil {
367
- ctx.Report(node, "Function must return a value.")
415
+ if ret == nil || ret.Expression != nil {
416
+ return
417
+ }
418
+ if opts.IgnoreInferredTypes && functionalEnclosingReturnTypeText(ctx, node) == "" {
419
+ return
368
420
  }
421
+ ctx.Report(node, "Function must return a value.")
369
422
  return
370
423
  }
371
- if functionalReturnTypeText(ctx, node) == "void" {
424
+ switch functionalReturnTypeText(ctx, node) {
425
+ case "void":
372
426
  ctx.Report(node, "Function must return a value.")
427
+ case "null":
428
+ if opts.AllowNull != nil && !*opts.AllowNull {
429
+ ctx.Report(node, "Function must return a value.")
430
+ }
431
+ case "undefined":
432
+ if opts.AllowUndefined != nil && !*opts.AllowUndefined {
433
+ ctx.Report(node, "Function must return a value.")
434
+ }
435
+ }
436
+ }
437
+
438
+ // functionalEnclosingReturnTypeText returns the declared return type text of the
439
+ // nearest function-like ancestor of `node`, or "" when that function declares
440
+ // none. A bare `return;` there is the only place the rule reports a void-ness it
441
+ // inferred instead of reading, which is what `ignoreInferredTypes` spares.
442
+ //
443
+ // The walk stops at the nearest function-like of ANY kind. Skipping a
444
+ // constructor or a set accessor, neither of which may annotate a return type,
445
+ // would attribute an enclosing function's annotation to a `return;` that has
446
+ // nothing to do with it. A get accessor may annotate one, and
447
+ // functionalReturnTypeText reads it.
448
+ func functionalEnclosingReturnTypeText(ctx *Context, node *shimast.Node) string {
449
+ for parent := node.Parent; parent != nil; parent = parent.Parent {
450
+ if !isFunctionLikeKind(parent) {
451
+ continue
452
+ }
453
+ return functionalReturnTypeText(ctx, parent)
373
454
  }
455
+ return ""
374
456
  }
375
457
 
376
458
  func (functionalNoThisExpressions) Check(ctx *Context, node *shimast.Node) {
@@ -418,6 +500,20 @@ func (functionalPreferPropertySignatures) Check(ctx *Context, node *shimast.Node
418
500
  func (functionalPreferReadonlyType) Check(ctx *Context, node *shimast.Node) {
419
501
  var opts functionalPreferReadonlyTypeOptions
420
502
  _ = ctx.DecodeOptions(&opts)
503
+ if opts.IgnoreInterface && hasAncestor(node, func(ancestor *shimast.Node) bool {
504
+ return ancestor.Kind == shimast.KindInterfaceDeclaration
505
+ }) {
506
+ return
507
+ }
508
+ if functionalIgnoreClassSkips(opts.IgnoreClass, node) {
509
+ return
510
+ }
511
+ if opts.AllowMutableReturnType && isFunctionLikeReturnTypePosition(node) {
512
+ return
513
+ }
514
+ if opts.IgnoreCollections && isFunctionalCollectionTypeNode(node) {
515
+ return
516
+ }
421
517
  switch node.Kind {
422
518
  case shimast.KindArrayType:
423
519
  if !isReadonlyTypeNode(node) {
@@ -451,10 +547,33 @@ func (functionalPreferReadonlyType) Check(ctx *Context, node *shimast.Node) {
451
547
  }
452
548
 
453
549
  func (functionalPreferTacit) Check(ctx *Context, node *shimast.Node) {
550
+ var opts functionalPreferTacitOptions
551
+ _ = ctx.DecodeOptions(&opts)
454
552
  text := compactFunctionalWhitespace(nodeText(ctx.File, node))
455
- if isTacitWrapperText(text) {
456
- ctx.Report(node, "Potentially unnecessary function wrapper.")
553
+ if !isTacitWrapperText(text) {
554
+ return
555
+ }
556
+ if opts.CheckMemberExpressions != nil && !*opts.CheckMemberExpressions &&
557
+ isTacitWrapperMemberCallee(text) {
558
+ return
457
559
  }
560
+ ctx.Report(node, "Potentially unnecessary function wrapper.")
561
+ }
562
+
563
+ // isTacitWrapperMemberCallee reports whether the wrapper's callee is a member
564
+ // expression (`service.handler`) rather than a bare identifier. `text` has
565
+ // already satisfied isTacitWrapperText, so the split and the `(` are present.
566
+ func isTacitWrapperMemberCallee(text string) bool {
567
+ parts := strings.Split(text, "=>")
568
+ if len(parts) != 2 {
569
+ return false
570
+ }
571
+ call := parts[1]
572
+ open := strings.LastIndex(call, "(")
573
+ if open <= 0 {
574
+ return false
575
+ }
576
+ return strings.Contains(call[:open], ".")
458
577
  }
459
578
 
460
579
  func (functionalReadonlyType) Check(ctx *Context, node *shimast.Node) {
@@ -595,27 +714,12 @@ func isDeclarationName(node *shimast.Node) bool {
595
714
  }
596
715
  }
597
716
 
717
+ // functionalReturnTypeText returns the declared return-type text of a
718
+ // signature-bearing node, or "" when it declares none. It reads the same
719
+ // signature table isFunctionLikeReturnTypePosition uses, so a get accessor is
720
+ // not mistaken for a declaration that cannot annotate its return type.
598
721
  func functionalReturnTypeText(ctx *Context, node *shimast.Node) string {
599
- var typeNode *shimast.Node
600
- switch node.Kind {
601
- case shimast.KindFunctionDeclaration:
602
- if decl := node.AsFunctionDeclaration(); decl != nil {
603
- typeNode = decl.Type
604
- }
605
- case shimast.KindFunctionExpression:
606
- if decl := node.AsFunctionExpression(); decl != nil {
607
- typeNode = decl.Type
608
- }
609
- case shimast.KindArrowFunction:
610
- if decl := node.AsArrowFunction(); decl != nil {
611
- typeNode = decl.Type
612
- }
613
- case shimast.KindMethodDeclaration:
614
- if decl := node.AsMethodDeclaration(); decl != nil {
615
- typeNode = decl.Type
616
- }
617
- }
618
- return strings.TrimSpace(nodeText(ctx.File, typeNode))
722
+ return strings.TrimSpace(nodeText(ctx.File, signatureReturnTypeNode(node)))
619
723
  }
620
724
 
621
725
  func functionalFunctionLikeName(node *shimast.Node) string {
@@ -757,6 +861,125 @@ func nilSafeFile(node *shimast.Node) *shimast.SourceFile {
757
861
  return nil
758
862
  }
759
863
 
864
+ // isFunctionLikeReturnTypePosition reports whether `node` is the return-type
865
+ // annotation of any signature-bearing declaration, or sits inside one. The rule
866
+ // visits type nodes, so a mutable array nested in the return type is the same
867
+ // position as the return type itself.
868
+ //
869
+ // Every kind that can carry a return-type annotation is listed: leaving call
870
+ // signatures, construct signatures, constructor types, or a get accessor out
871
+ // would let the same option answer differently for the same position depending
872
+ // on how the signature was spelled.
873
+ func isFunctionLikeReturnTypePosition(node *shimast.Node) bool {
874
+ for current := node; current != nil && current.Parent != nil; current = current.Parent {
875
+ typeNode := signatureReturnTypeNode(current.Parent)
876
+ if typeNode != nil && typeNode == current {
877
+ return true
878
+ }
879
+ }
880
+ return false
881
+ }
882
+
883
+ // signatureReturnTypeNode returns the declared return-type node of `node`, or
884
+ // nil when `node` carries no signature or declares no return type.
885
+ //
886
+ // Do not replace this table with typescript-go's own FunctionLikeData().Type:
887
+ // an index signature embeds the same base, so that accessor also returns the
888
+ // value type of `{ [k: string]: string[] }`, which is not a return type. The
889
+ // three kinds this table omits, a constructor, a set accessor, and an index
890
+ // signature, are exactly the ones whose Type field means something else.
891
+ func signatureReturnTypeNode(node *shimast.Node) *shimast.Node {
892
+ switch node.Kind {
893
+ case shimast.KindFunctionDeclaration:
894
+ if decl := node.AsFunctionDeclaration(); decl != nil {
895
+ return decl.Type
896
+ }
897
+ case shimast.KindFunctionExpression:
898
+ if decl := node.AsFunctionExpression(); decl != nil {
899
+ return decl.Type
900
+ }
901
+ case shimast.KindArrowFunction:
902
+ if decl := node.AsArrowFunction(); decl != nil {
903
+ return decl.Type
904
+ }
905
+ case shimast.KindMethodDeclaration:
906
+ if decl := node.AsMethodDeclaration(); decl != nil {
907
+ return decl.Type
908
+ }
909
+ case shimast.KindMethodSignature:
910
+ if decl := node.AsMethodSignatureDeclaration(); decl != nil {
911
+ return decl.Type
912
+ }
913
+ case shimast.KindGetAccessor:
914
+ if decl := node.AsGetAccessorDeclaration(); decl != nil {
915
+ return decl.Type
916
+ }
917
+ case shimast.KindFunctionType:
918
+ if decl := node.AsFunctionTypeNode(); decl != nil {
919
+ return decl.Type
920
+ }
921
+ case shimast.KindConstructorType:
922
+ if decl := node.AsConstructorTypeNode(); decl != nil {
923
+ return decl.Type
924
+ }
925
+ case shimast.KindCallSignature:
926
+ if decl := node.AsCallSignatureDeclaration(); decl != nil {
927
+ return decl.Type
928
+ }
929
+ case shimast.KindConstructSignature:
930
+ if decl := node.AsConstructSignatureDeclaration(); decl != nil {
931
+ return decl.Type
932
+ }
933
+ }
934
+ return nil
935
+ }
936
+
937
+ // isFunctionalClassMemberPosition reports whether `node` sits inside a class,
938
+ // and whether that position is a field. `ignoreClass: true` skips anything
939
+ // under a class, its heritage clause and type parameters included, the same
940
+ // ancestor test `ignoreInterface` applies. `"fieldsOnly"` narrows that to field
941
+ // declarations, leaving methods, accessors, and constructor parameters checked.
942
+ func isFunctionalClassMemberPosition(node *shimast.Node) (inClass bool, inField bool) {
943
+ for parent := node.Parent; parent != nil; parent = parent.Parent {
944
+ switch parent.Kind {
945
+ case shimast.KindPropertyDeclaration:
946
+ inField = true
947
+ case shimast.KindClassDeclaration, shimast.KindClassExpression:
948
+ return true, inField
949
+ }
950
+ }
951
+ return false, false
952
+ }
953
+
954
+ // functionalIgnoreClassSkips resolves the `boolean | "fieldsOnly"` option
955
+ // against a visited node's class position.
956
+ func functionalIgnoreClassSkips(option interface{}, node *shimast.Node) bool {
957
+ if option == nil || option == false {
958
+ return false
959
+ }
960
+ inClass, inField := isFunctionalClassMemberPosition(node)
961
+ if !inClass {
962
+ return false
963
+ }
964
+ if option == "fieldsOnly" {
965
+ return inField
966
+ }
967
+ return option == true
968
+ }
969
+
970
+ // isFunctionalCollectionTypeNode reports whether `node` is an array, tuple, or
971
+ // mutable built-in collection reference, the set `ignoreCollections` spares.
972
+ func isFunctionalCollectionTypeNode(node *shimast.Node) bool {
973
+ switch node.Kind {
974
+ case shimast.KindArrayType, shimast.KindTupleType:
975
+ return true
976
+ case shimast.KindTypeReference:
977
+ return isMutableTypeReference(node)
978
+ default:
979
+ return false
980
+ }
981
+ }
982
+
760
983
  func isMutableTypeReference(node *shimast.Node) bool {
761
984
  ref := node.AsTypeReferenceNode()
762
985
  if ref == nil || ref.TypeName == nil {
@@ -317,12 +317,14 @@ func parameterPropertyName(param *shimast.Node) (string, bool) {
317
317
  return name, name != ""
318
318
  }
319
319
 
320
+ // isParameterProperty is the package's shared parameter-property predicate.
321
+ // The compiler's own mask is the source: a restated keyword list is what left
322
+ // `override` out of format/parameter-properties (#1131), and this predicate
323
+ // feeds six rules, so a restatement here would be five more chances at the same
324
+ // drift.
320
325
  func isParameterProperty(param *shimast.Node) bool {
321
- return hasModifier(param, shimast.KindPublicKeyword) ||
322
- hasModifier(param, shimast.KindPrivateKeyword) ||
323
- hasModifier(param, shimast.KindProtectedKeyword) ||
324
- hasModifier(param, shimast.KindReadonlyKeyword) ||
325
- hasModifier(param, shimast.KindOverrideKeyword)
326
+ return param != nil &&
327
+ param.ModifierFlags()&shimast.ModifierFlagsParameterPropertyModifier != 0
326
328
  }
327
329
 
328
330
  func thisPropertyAssignment(stmt *shimast.Node) (property string, value string, ok bool) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ttsc/lint",
3
- "version": "0.25.0",
3
+ "version": "0.26.0",
4
4
  "description": "Reference ttsc plugin: ESLint-style lint rules over the TypeScript-Go Program used by the type-check pass.",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",
@@ -37,7 +37,7 @@
37
37
  "@types/node": "^25.3.0",
38
38
  "rimraf": "^6.1.2",
39
39
  "typescript": "^7.0.2",
40
- "ttsc": "0.25.0"
40
+ "ttsc": "0.26.0"
41
41
  },
42
42
  "repository": {
43
43
  "type": "git",
package/rule/rule.go CHANGED
@@ -262,15 +262,27 @@ type RelatedInformation struct {
262
262
  // be replaced as a whole.
263
263
  //
264
264
  // Application policy: a rule may emit several `TextEdit`s in one
265
- // `ReportFix` / `ReportRangeFix` call, in any order. The host treats the
266
- // per-pass edit set as a candidate list. Within a single fix pass, edits
267
- // must not overlap each other; when two edits cover overlapping ranges
268
- // (either from one rule emitting multiple edits in one call, or from two
269
- // different rules in the same pass), the host applies the earliest-starting
270
- // / shortest edit and silently drops the rest. There is no diagnostic for
271
- // dropped edits, and the host does not currently report when a comment
272
- // falls inside a deletion range. Design fixes so each finding emits one
273
- // contiguous TextEdit covering the entire replacement region.
265
+ // `ReportFix` / `ReportRangeFix` call, in any order. The unit the host
266
+ // resolves conflicts on is the FINDING, not the individual edit. Within one
267
+ // fix pass the host considers each finding's edits as one group, earliest
268
+ // group first, and accepts a group only when every member coexists with the
269
+ // edits already accepted. If any member would be dropped, the whole group is
270
+ // skipped, so a multi-edit fix never half-applies. The skipped finding is not
271
+ // lost: the next cascade pass re-runs the rule against the rewritten source
272
+ // and the fix applies then, or the cascade converges without it.
273
+ //
274
+ // A finding's own edits must therefore not overlap each other either, or the
275
+ // finding can never apply. Exact duplicates within one finding are collapsed
276
+ // rather than treated as a conflict, so repeating an identical edit is
277
+ // harmless. Nothing diagnoses a skipped group, and the host does not report
278
+ // when a comment falls inside a deletion range.
279
+ //
280
+ // Emit the narrowest edits that express the rewrite. Several small
281
+ // non-overlapping edits contend for less source than one wide replacement and
282
+ // are the shape the atomic applier exists to support. Built-ins that ship
283
+ // multi-edit fixes include `typescript/no-import-type-side-effects`,
284
+ // `format/whitespace`, `format/indent`, `unicorn/prevent-abbreviations`, and
285
+ // `unicorn/template-indent`.
274
286
  type TextEdit struct {
275
287
  Pos int
276
288
  End int
@@ -80,24 +80,45 @@ export interface ITtscLintFunctionalNoThrowStatementsRuleOptions {
80
80
 
81
81
  /** `functional/no-mixed-types` rule options. */
82
82
  export interface ITtscLintFunctionalNoMixedTypesRuleOptions {
83
- /** Check interface member kinds. */
83
+ /**
84
+ * Check interface member kinds.
85
+ *
86
+ * @default true
87
+ */
84
88
  checkInterfaces?: boolean;
85
89
 
86
- /** Check type-literal member kinds. */
90
+ /**
91
+ * Check type-literal member kinds.
92
+ *
93
+ * @default true
94
+ */
87
95
  checkTypeLiterals?: boolean;
88
96
  }
89
97
 
90
98
  /** `functional/no-return-void` rule options. */
91
99
  export interface ITtscLintFunctionalNoReturnVoidRuleOptions {
92
- /** Permit a function that returns `null` to satisfy the rule. */
100
+ /**
101
+ * Permit a function whose declared return type is `null`. Set `false` to
102
+ * reject it the way a declared `void` is rejected.
103
+ *
104
+ * @default true
105
+ */
93
106
  allowNull?: boolean;
94
107
 
95
- /** Permit a function that returns `undefined` to satisfy the rule. */
108
+ /**
109
+ * Permit a function whose declared return type is `undefined`. Set `false` to
110
+ * reject it the way a declared `void` is rejected.
111
+ *
112
+ * @default true
113
+ */
96
114
  allowUndefined?: boolean;
97
115
 
98
116
  /**
99
- * Skip functions whose return type is inferred to be `void` rather than
100
- * declared explicitly.
117
+ * Skip a bare `return;` inside a function that declares no return type. That
118
+ * statement is the one place the rule rejects a void-ness it inferred rather
119
+ * than read from an annotation.
120
+ *
121
+ * @default false
101
122
  */
102
123
  ignoreInferredTypes?: boolean;
103
124
  }
@@ -105,7 +126,8 @@ export interface ITtscLintFunctionalNoReturnVoidRuleOptions {
105
126
  /** `functional/prefer-immutable-types` rule options. */
106
127
  export interface ITtscLintFunctionalPreferImmutableTypesRuleOptions extends ITtscLintFunctionalPatternOptions {
107
128
  /**
108
- * Minimum accepted immutability. The native subset treats any configured
129
+ * Minimum accepted immutability. Reserved for upstream-compatible configs;
130
+ * the native subset computes no immutability level and treats any configured
109
131
  * value as readonly-required.
110
132
  */
111
133
  enforcement?:
@@ -118,31 +140,62 @@ export interface ITtscLintFunctionalPreferImmutableTypesRuleOptions extends ITts
118
140
 
119
141
  /** `functional/prefer-readonly-type` rule options. */
120
142
  export interface ITtscLintFunctionalPreferReadonlyTypeRuleOptions extends ITtscLintFunctionalPatternOptions {
121
- /** Permit mutation of locals while still policing exported types. */
143
+ /**
144
+ * Permit mutation of locals while still policing exported types. Reserved for
145
+ * upstream-compatible configs; the native subset reads type annotations and
146
+ * models no local-versus-exported distinction.
147
+ */
122
148
  allowLocalMutation?: boolean;
123
149
 
124
- /** Permit a mutable return type even when parameters must be readonly. */
150
+ /**
151
+ * Permit a mutable return type even when parameters must be readonly. Covers
152
+ * every signature that can declare one, including call and construct
153
+ * signatures, constructor types, and a get accessor.
154
+ *
155
+ * @default false
156
+ */
125
157
  allowMutableReturnType?: boolean;
126
158
 
127
- /** Also check property positions that have no explicit type annotation. */
159
+ /**
160
+ * Also check property positions that have no explicit type annotation.
161
+ * Reserved for upstream-compatible configs; judging an unannotated position
162
+ * needs the type checker, which this rule does not use.
163
+ */
128
164
  checkImplicit?: boolean;
129
165
 
130
- /** Skip array / tuple / `Map` / `Set` types. */
166
+ /**
167
+ * Skip array / tuple / `Map` / `Set` types.
168
+ *
169
+ * @default false
170
+ */
131
171
  ignoreCollections?: boolean;
132
172
 
133
173
  /**
134
- * Skip class fields. `"fieldsOnly"` keeps the rule active for non-field class
135
- * members.
174
+ * Skip class members. `true` skips anything under a class, its heritage
175
+ * clause and type parameters included; `"fieldsOnly"` narrows that to field
176
+ * declarations and keeps methods, accessors, and constructor parameters
177
+ * checked.
178
+ *
179
+ * @default false
136
180
  */
137
181
  ignoreClass?: boolean | "fieldsOnly";
138
182
 
139
- /** Skip interface members entirely. */
183
+ /**
184
+ * Skip interface members entirely.
185
+ *
186
+ * @default false
187
+ */
140
188
  ignoreInterface?: boolean;
141
189
  }
142
190
 
143
191
  /** `functional/prefer-tacit` rule options. */
144
192
  export interface ITtscLintFunctionalPreferTacitRuleOptions {
145
- /** Check member expressions such as `x => service.map(x)`. */
193
+ /**
194
+ * Check member expressions such as `x => service.map(x)`. Set `false` to keep
195
+ * the rule on bare-identifier callees only.
196
+ *
197
+ * @default true
198
+ */
146
199
  checkMemberExpressions?: boolean;
147
200
  }
148
201
 
@@ -167,7 +220,11 @@ export interface ITtscLintFunctionalTypeDeclarationImmutabilityRule {
167
220
  */
168
221
  immutability?: "ReadonlyShallow" | "ReadonlyDeep" | "Immutable" | "Mutable";
169
222
 
170
- /** Comparator applied to the immutability level above. */
223
+ /**
224
+ * Comparator applied to the immutability level above. Reserved for
225
+ * upstream-compatible configs alongside `immutability`: the native subset
226
+ * computes no immutability level, so there is nothing to compare.
227
+ */
171
228
  comparator?:
172
229
  | "Less"
173
230
  | "AtMost"