]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
feat(types/reactivity): use `DeepReadonly` type for `readonly` return type (#1462)
authorPick <pickchen@tencent.com>
Wed, 15 Jul 2020 13:27:21 +0000 (21:27 +0800)
committerGitHub <noreply@github.com>
Wed, 15 Jul 2020 13:27:21 +0000 (09:27 -0400)
close #1452

.github/contributing.md
packages/reactivity/src/reactive.ts
test-dts/reactivity.test-d.ts [new file with mode: 0644]

index f890f31c2dddc2a3b550122300800e2ee04b9962..df3efd9abfc3ff4874a1f4badd4f1d3e9a1ae068 100644 (file)
@@ -244,7 +244,7 @@ Test coverage is continuously deployed at https://vue-next-coverage.netlify.app/
 
 This project uses [tsd](https://github.com/SamVerschueren/tsd) to test the built definition files (`*.d.ts`).
 
-Type tests are located in the `test-dts` directory. To run the dts tests, run `yarn test-dts`. Note that the type test requires all relevant `*.d.ts` files to be built first (and the script does it for you). Once the `d.ts` files are built and up-to-date, the tests can be re-run by simply running `./node_modules/.bin/tsd`.
+Type tests are located in the `test-dts` directory. To run the dts tests, run `yarn test-dts`. Note that the type test requires all relevant `*.d.ts` files to be built first (and the script does it for you). Once the `d.ts` files are built and up-to-date, the tests can be re-run by simply running `yarn test-dts`.
 
 ## Financial Contribution
 
index 0dfec8a9a968c6a285059fa70d68d296b89e4e31..1f01c393d0f4bc24570c3bf80bd956f2f35cb88b 100644 (file)
@@ -72,9 +72,31 @@ export function shallowReactive<T extends object>(target: T): T {
   )
 }
 
+type Primitive = string | number | boolean | bigint | symbol | undefined | null
+type Builtin = Primitive | Function | Date | Error | RegExp
+type DeepReadonly<T> = T extends Builtin
+  ? T
+  : T extends Map<infer K, infer V>
+    ? ReadonlyMap<DeepReadonly<K>, DeepReadonly<V>>
+    : T extends ReadonlyMap<infer K, infer V>
+      ? ReadonlyMap<DeepReadonly<K>, DeepReadonly<V>>
+      : T extends WeakMap<infer K, infer V>
+        ? WeakMap<DeepReadonly<K>, DeepReadonly<V>>
+        : T extends Set<infer U>
+          ? ReadonlySet<DeepReadonly<U>>
+          : T extends ReadonlySet<infer U>
+            ? ReadonlySet<DeepReadonly<U>>
+            : T extends WeakSet<infer U>
+              ? WeakSet<DeepReadonly<U>>
+              : T extends Promise<infer U>
+                ? Promise<DeepReadonly<U>>
+                : T extends {}
+                  ? { readonly [K in keyof T]: DeepReadonly<T[K]> }
+                  : Readonly<T>
+
 export function readonly<T extends object>(
   target: T
-): Readonly<UnwrapNestedRefs<T>> {
+): DeepReadonly<UnwrapNestedRefs<T>> {
   return createReactiveObject(
     target,
     true,
diff --git a/test-dts/reactivity.test-d.ts b/test-dts/reactivity.test-d.ts
new file mode 100644 (file)
index 0000000..edccd4f
--- /dev/null
@@ -0,0 +1,9 @@
+import { readonly, describe, expectError } from './index'\r
+\r
+describe('should support DeepReadonly', () => {\r
+  const r = readonly({ obj: { k: 'v' } })\r
+  // @ts-expect-error\r
+  expectError((r.obj = {}))\r
+  // @ts-expect-error\r
+  expectError((r.obj.k = 'x'))\r
+})\r