有类型任务的:
type Task = {
id: string;
prop1: string;
prop2: number;
}
我正在try 正确地键入一个参数,以便表达对任务的更新:
- ID-必填-查找合适的任务
- 任意数量的props -可选-任务props 的更新
我想出了两个替代方案:
type TaskUpdate1 = Pick<Task, 'id'> & Partial<Omit<Task, 'id'>>;
type TaskUpdate2 = Pick<Task, 'id'> & Partial<Task>;
在我看来,它们是相同的,但两个类型断言库声称它们是不同的:
import { Expect, Equal } from 'type-testing';
import { assert, _ } from "spec.ts";
type Task = {
id: string;
prop1: string;
prop2: number;
}
type TaskUpdate1 = Pick<Task, 'id'> & Partial<Omit<Task, 'id'>>;
type TaskUpdate2 = Pick<Task, 'id'> & Partial<Task>;
type test_0 = Expect<Equal<TaskUpdate1, TaskUpdate2>>;
var x = {} as TaskUpdate1;
var y = {} as TaskUpdate2;
assert(x, y);
这些类型有什么不同(如果有,有什么不同?换句话说:是否存在属于一个而不属于另一个的值?),或者是类型测试代码中的缺陷?
Update个
这个问题显然是关于类型测试和规范的知识 我内联了这些库中的类型,以使问题更加独立:
/* type-testing: https://github.com/MichiganTypeScript/type-testing/ */
export type Equal<A, B> =
(<T>() => T extends A ? 1 : 2) extends
(<T>() => T extends B ? 1 : 2)
? true
: false;
export type Expect<T extends true> = Equal<T, true>;
/* spec.ts: https://github.com/aleclarson/spec.ts */
// Give "any" its own class
export class Any {
private _: true = true;
}
type TestExact<Left, Right> =
(<U>() => U extends Left ? 1 : 0) extends (<U>() => U extends Right ? 1 : 0) ? Any : never;
type IsAny<T> = Any extends T ? ([T] extends [Any] ? 1 : 0) : 0;
export type Test<Left, Right> = IsAny<Left> extends 1
? IsAny<Right> extends 1
? 1
: "❌ Left type is 'any' but right type is not"
: IsAny<Right> extends 1
? "❌ Right type is 'any' but left type is not"
: [Left] extends [Right]
? [Right] extends [Left]
? Any extends TestExact<Left, Right>
? 1
: "❌ Unexpected or missing 'readonly' property"
: "❌ Right type is not assignable to left type"
: "❌ Left type is not assignable to right type";
type Assert<T, U> = U extends 1
? T // No error.
: IsAny<T> extends 1
? never // Ensure "any" is refused.
: U; // Return the error message.
export const assert: <Left, Right>(
left: Assert<Left, Test<Left, Right>>,
right: Assert<Right, Test<Left, Right>>
) => Right = () => ({}) as any;
/* My code */
type Task = {
id: string;
prop1: string;
prop2: number;
}
type TaskUpdate1 = Pick<Task, 'id'> & Partial<Omit<Task, 'id'>>;
type TaskUpdate2 = Pick<Task, 'id'> & Partial<Task>;
type test_0 = Expect<Equal<TaskUpdate1, TaskUpdate2>>;
var x = {} as TaskUpdate1;
var y = {} as TaskUpdate2;
assert(x, y);