Skip to content

Commit

Permalink
fix(type-utils): check IndexSignature internals when checking isTypeR…
Browse files Browse the repository at this point in the history
…eadonly

fix #3714
  • Loading branch information
RebeccaStevens committed Jan 9, 2022
1 parent 9ffd4f7 commit 920a0af
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 24 deletions.
54 changes: 38 additions & 16 deletions packages/type-utils/src/isTypeReadonly.ts
Expand Up @@ -107,9 +107,18 @@ function isTypeReadonlyObject(
function checkIndexSignature(kind: ts.IndexKind): Readonlyness {
const indexInfo = checker.getIndexInfoOfType(type, kind);
if (indexInfo) {
return indexInfo.isReadonly
? Readonlyness.Readonly
: Readonlyness.Mutable;
if (!indexInfo.isReadonly) {
return Readonlyness.Mutable;
}

return (
isTypeReadonlyRecurser(
checker,
indexInfo.keyType,
options,
seenTypes,
) && isTypeReadonlyRecurser(checker, indexInfo.type, options, seenTypes)
);
}

return Readonlyness.UnknownType;
Expand All @@ -119,20 +128,33 @@ function isTypeReadonlyObject(
if (properties.length) {
// ensure the properties are marked as readonly
for (const property of properties) {
if (
!(
isPropertyReadonlyInType(type, property.getEscapedName(), checker) ||
(options.treatMethodsAsReadonly &&
property.valueDeclaration !== undefined &&
hasSymbol(property.valueDeclaration) &&
isSymbolFlagSet(
property.valueDeclaration.symbol,
ts.SymbolFlags.Method,
))
)
) {
return Readonlyness.Mutable;
if (options.treatMethodsAsReadonly) {
if (
property.valueDeclaration !== undefined &&
hasSymbol(property.valueDeclaration) &&
isSymbolFlagSet(
property.valueDeclaration.symbol,
ts.SymbolFlags.Method,
)
) {
continue;
}

const lastDeclaration = property.getDeclarations()?.at(-1);
if (
lastDeclaration !== undefined &&
hasSymbol(lastDeclaration) &&
isSymbolFlagSet(lastDeclaration.symbol, ts.SymbolFlags.Method)
) {
continue;
}
}

if (isPropertyReadonlyInType(type, property.getEscapedName(), checker)) {
continue;
}

return Readonlyness.Mutable;
}

// all properties were readonly
Expand Down
14 changes: 6 additions & 8 deletions packages/type-utils/tests/isTypeReadonly.test.ts
Expand Up @@ -264,15 +264,13 @@ describe('isTypeReadonly', () => {
});

describe('is not readonly', () => {
describe('default options', () => {
it('fails with a mutable PropertySignature inside a readonly IndexSignature', () => {
const { type, checker } = getType(
`type Test = { readonly [key: string]: { foo: string[]; }; };`,
);
it('fails with a mutable PropertySignature inside a readonly IndexSignature', () => {
const { type, checker } = getType(
`type Test = { readonly [key: string]: { foo: string[]; }; };`,
);

const result = isTypeReadonly(checker, type);
expect(result).toBe(false);
});
const result = isTypeReadonly(checker, type);
expect(result).toBe(false);
});
});
});
Expand Down

0 comments on commit 920a0af

Please sign in to comment.