Typescript 如何选择不是某种类型键的对象属性?

Typescript 如何选择不是某种类型键的对象属性?,typescript,Typescript,假设一个类型 type Thing = { name: string; // other properties }; …还有一个像这样的物体 const obj = { name: 'blah', // other properties from Thing someProp: true, otherProp: 123, yetAnotherProp: 'yay', }; …我希望能够将obj中的属性缩小到Thing中没有的属性,因此结

假设一个类型

type Thing = {
    name: string;
    // other properties
};
…还有一个像这样的物体

const obj = {
    name: 'blah',
    // other properties from Thing
    someProp: true,
    otherProp: 123,
    yetAnotherProp: 'yay',
};
…我希望能够将
obj
中的属性缩小到
Thing
中没有的属性,因此结果将是:

const objWithoutThing = {
    // no properties from `Thing`
    someProp: true,
    otherProp: 123,
    yetAnotherProp: 'yay',
};
例如:


如果您使用的是TypeScript v3.5或更高版本,则可以使用
省略

type Obj = {
    name: string;
    someProp: boolean;
    otherProp: number;
    yetAnotherProp: string;
}

type Thing = {
    name: string;
}

type ObjWithoutThing = Omit<Obj, keyof Thing>;

const objWithoutThing: ObjWithoutThing = {
    // no properties from `Thing`
    someProp: true,
    otherProp: 123,
    yetAnotherProp: 'yay',
};
类型Obj={
名称:字符串;
someProp:布尔;
其他属性:数字;
yetAnotherProp:字符串;
}
类型对象={
名称:字符串;
}
类型objwithout=省略;
常量objwithout:objwithout={
//没有任何东西的属性`
是的,
其他项目:123,
yetAnotherProp:‘耶’,
};

如果您使用的是TypeScript v3.5或更高版本,您可以使用
省略

type Obj = {
    name: string;
    someProp: boolean;
    otherProp: number;
    yetAnotherProp: string;
}

type Thing = {
    name: string;
}

type ObjWithoutThing = Omit<Obj, keyof Thing>;

const objWithoutThing: ObjWithoutThing = {
    // no properties from `Thing`
    someProp: true,
    otherProp: 123,
    yetAnotherProp: 'yay',
};
类型Obj={
名称:字符串;
someProp:布尔;
其他属性:数字;
yetAnotherProp:字符串;
}
类型对象={
名称:字符串;
}
类型objwithout=省略;
常量objwithout:objwithout={
//没有任何东西的属性`
是的,
其他项目:123,
yetAnotherProp:‘耶’,
};

您不能自动执行此操作。TypeScript的静态类型系统,包括
对象
类型别名的定义,在代码传输到JavaScript时获取。因此,当您试图从
obj
中省略
Thing
的键时,在运行时将没有什么可以执行的操作


如果希望在运行时省略
Thing
的键,则需要显式创建一个此类键的列表,作为运行时存在的值。通过一些努力,您至少可以让编译器检查您是否正确地执行了此操作。例如:

const thingKeys = ["name"] as const;

type ThingKeysCheck<
    T extends typeof thingKeys[number] = keyof Thing,
    // --------------------------------> ~~~~~~~~~~~
    // error here if thingKeys has missing keys
    U extends keyof Thing = typeof thingKeys[number]
    // -------------------> ~~~~~~~~~~~~~~~~~~~~~~~~
    // error here if thingKeys has extra keys
    > = void;
我在该函数的实现过程中做了很多工作来平息编译器的抱怨;它不能很好地验证您是否实际创建了类型为
ommit
的有效对象。无论如何,它基本上与您编写的实现相同


让我们看看它是否有效:

const objWithoutThing = withoutThing(obj);
console.log(objWithoutThing.someProp); // true
console.log(objWithoutThing.otherProp.toFixed(2)); // 123.00
console.log(objWithoutThing.yetAnotherProp.toUpperCase()); // "YAY"
console.log(objWithoutThing.name); // undefined
// -----------------------> ~~~~
// Property 'name' does not exist
我觉得不错



您不能自动执行此操作。TypeScript的静态类型系统,包括
对象
类型别名的定义,在代码传输到JavaScript时获取。因此,当您试图从
obj
中省略
Thing
的键时,在运行时将没有什么可以执行的操作


如果希望在运行时省略
Thing
的键,则需要显式创建一个此类键的列表,作为运行时存在的值。通过一些努力,您至少可以让编译器检查您是否正确地执行了此操作。例如:

const thingKeys = ["name"] as const;

type ThingKeysCheck<
    T extends typeof thingKeys[number] = keyof Thing,
    // --------------------------------> ~~~~~~~~~~~
    // error here if thingKeys has missing keys
    U extends keyof Thing = typeof thingKeys[number]
    // -------------------> ~~~~~~~~~~~~~~~~~~~~~~~~
    // error here if thingKeys has extra keys
    > = void;
我在该函数的实现过程中做了很多工作来平息编译器的抱怨;它不能很好地验证您是否实际创建了类型为
ommit
的有效对象。无论如何,它基本上与您编写的实现相同


让我们看看它是否有效:

const objWithoutThing = withoutThing(obj);
console.log(objWithoutThing.someProp); // true
console.log(objWithoutThing.otherProp.toFixed(2)); // 123.00
console.log(objWithoutThing.yetAnotherProp.toUpperCase()); // "YAY"
console.log(objWithoutThing.name); // undefined
// -----------------------> ~~~~
// Property 'name' does not exist
我觉得不错



对不起,但是附加属性可以是字面上的任何东西,所以我根本无法定义
objwithout
,它的定义是“任何键,除了
Thing
中的键”。对不起,但是附加属性可以是字面上的任何东西,所以我根本无法定义
objwithout
,它的定义是“任何键,除了
东西
”中的键。是的,这很有意义,而且很有效。我希望TS有一些神奇的
复制键
,或者可以提取
字符串[]
在运行时。不过我会这样做。谢谢。如果你想要另一个…是的,这很有意义并且有效。我希望TS有一些神奇的
复制键,或者在运行时提取
字符串[]
的键。不过我会这样做。谢谢。如果你想要另一个。。。