在Typescript中,我可以创建一个映射类型来强制要求属性吗?

在Typescript中,我可以创建一个映射类型来强制要求属性吗?,typescript,mapped-types,Typescript,Mapped Types,在Typescript中,我们有可以将属性从一种类型映射到另一种类型的映射类型 一个常见的例子是分部类型,它使泛型类型上的所有属性都是“可选的” 我想实现相反的效果,比如说Required,所有的属性都是“Required”,不管它们的可选性如何 这可能吗 (因为我的问题是肤浅的,请看更新!) 更新: 一些上下文 我正在学习映射类型,并受到文档的启发 您将得到一个ProxyObservable类型,其中每个属性都是相同类型的可观察属性,但也有子属性(也可观察)的匹配导航属性 因为它无法辨别与Ob

在Typescript中,我们有可以将属性从一种类型映射到另一种类型的映射类型

一个常见的例子是分部类型,它使泛型类型上的所有属性都是“可选的”

我想实现相反的效果,比如说Required,所有的属性都是“Required”,不管它们的可选性如何

这可能吗

(因为我的问题是肤浅的,请看更新!)

更新:

一些上下文

我正在学习映射类型,并受到文档的启发

您将得到一个
ProxyObservable
类型,其中每个属性都是相同类型的可观察属性,但也有子属性(也可观察)的匹配导航属性

因为它无法辨别与Observable联合的类型是“未定义”还是我们定义的对象。这就是我的问题所在

但是。。。我现在还看到,这不是“可选”属性的问题,而是一般有区别的联合类型的问题

我意识到,给定正确的上下文,Typescript可能能够推断
foo.myObject
属性的类型。我尝试了一些变化:

foo.myObject!.someValue //<- Nope
foo.myObject ? foo.myObject.someValue : ... //<- Nope
if(foo.myObject) foo.myObject.someValue //<- Nope

foo.myObject!。someValue/不幸的是,我不认为您可以用类型映射来实现它。(很高兴被证明是错的,如果是的话,我会删除这个答案)。这对我来说是一个问题,但一些建议的解决方案对我来说不起作用

一般来说,我认为你需要类型减法。您可以使用减法从类型联合
T | undefined
中“删除”
undefined

我所知道的“强制”某些属性存在的唯一方法是使用具有显式已知属性的并集:

interface Foo {
  a: number;
}

let a: Partial<Foo> & { a: number } = {}
接口Foo{
a:数字;
}
设a:Partial&{a:number}={}
类型“{}”不能分配给类型“{a:number;}”。 类型“{}”中缺少属性“a”

例如:

class Person {
  id: string;
  name: string = "John";
  address: string = "empty";

  constructor(init: Partial<Person> & { id: string }) {
    Object.assign(this, init);
  }
}   

let person = new Person({ id: "1234" });
班级人员{
id:字符串;
名称:string=“John”;
地址:string=“empty”;
构造函数(init:Partial&{id:string}){
赋值(this,init);
}
}   
let person=新的人({id:“1234”});

你强迫id在那里,但其他一切都是局部的

正如@MeirionHughes所说,类型操作符的功能还不足以实现这一点

你为什么要这个?您可以使用的一件事是生成一个函数,该函数接受
Partial
,并返回
T
。这实际上在类型级别工作,但实际上不可能实现这样的函数,因为它需要能够在运行时获取(比如)空对象,并且神奇地知道要向其添加哪些属性。不行。但无论如何,这里有一个声明:

declare function unpartial<T>(t: Partial<T>): T;
如果您有
unparatial()
函数和
Stuff
的实例,则可以调用它并获得所需类型的对象:

declare const stuff: Stuff;
const unpartialStuff = unpartial(stuff);
type UnpartialStuff = typeof unpartialStuff;
// UnpartialStuff = { 
//  foo: string; 
//  bar: number; 
//  baz: boolean; 
//  qux: () => void;
// }
这很好,但在运行时并不重要,因为
unparatial
只是声明的,而不是实现的。你可以吃蛋糕,也可以这样做:

const unpartialStuff = (true as false) || unpartial(null! as Stuff);
type UnpartialStuff = typeof unpartialStuff;
(true as false)
在运行时计算为
true
,但类型系统将其解释为
false
,这意味着在运行时
unparatial()
永远不会被调用,但编译器认为它会调用并为您计算类型。既然我们对编译器撒谎,那么我们最好不要在
Stuff
的伪实例上浪费一个变量名;因此
(null!as Stuff)

让我们把这些放在一个地方:

declare function unpartial<T>(t: Partial<T>): T;
interface Stuff {
  foo?: string;
  bar?: number;
  baz: boolean;
  qux: () => void; 
}
const unpartialStuff = (true as false) || unpartial(null! as Stuff);
type UnpartialStuff = typeof unpartialStuff;
声明函数不可分析(t:Partial):t;
接口材料{
foo?:字符串;
条?:编号;
baz:布尔型;
qux:()=>无效;
}
const unpartialStuff=(true为false)| | unparative(null!as Stuff);
类型UnpartialStuff=类型UnpartialStuff;
好了,你撒谎和作弊,欺骗编译器从
Stuff
计算
UnpartialStuff
。在你的情况下,这个诡计是否值得,这取决于你。祝你好运


更新 谁能告诉我为什么不

嗯,它不起作用的原因是
keyof(A | B)
=
(A的keyof)和(B的keyof)
,所以
keyof(A |未定义)
=
(A的keyof)&never
=
never
。因此,当您尝试映射可能未定义的
类型的键时,您会发现没有键

这种身份是“安全”身份,因为您知道的唯一存在于工会上的钥匙是存在于每个组成部分中的钥匙。就是


对于在联合键上的映射,您需要一些不安全的操作,或条件映射类型或其他类型运算符,以便可以映射每个组成部分。不幸的是,这些类型运算符目前不存在于TypeScript中 这现在是可能的,并且内置在TypeScript中,作为从TypeScript 2.8开始所需的
类型

以下是它的定义:

/**
 * Make all properties in T required
 */
type Required<T> = {
    [P in keyof T]-?: T[P];
};
/**
*使T中的所有属性都是必需的
*/
所需类型={
[P in keyof T]-?:T[P];
};

这既美丽又邪恶,谢谢你花时间写出来。出于学术兴趣,我更新了我的帖子,为我的问题提供了更好的背景!我会是v。如果你能看一看,我很高兴!我发布了一个更新,但我没有任何解决方案,只是对发生的事情进行了解释。感谢与类型减法的链接,我很高兴看到它出现在路线图上。多有趣的特色啊!另外,我认为这是一种覆盖某些属性的非常有趣的技术,不幸的是,我事先不知道特定的属性定义。我还发布了一些额外的内容和更新我的问题,如果你有时间,我会非常高兴
declare function unpartial<T>(t: Partial<T>): T;
interface Stuff {
  foo?: string;
  bar?: number;
  baz: boolean;
  qux: () => void; 
}
declare const stuff: Stuff;
const unpartialStuff = unpartial(stuff);
type UnpartialStuff = typeof unpartialStuff;
// UnpartialStuff = { 
//  foo: string; 
//  bar: number; 
//  baz: boolean; 
//  qux: () => void;
// }
const unpartialStuff = (true as false) || unpartial(null! as Stuff);
type UnpartialStuff = typeof unpartialStuff;
declare function unpartial<T>(t: Partial<T>): T;
interface Stuff {
  foo?: string;
  bar?: number;
  baz: boolean;
  qux: () => void; 
}
const unpartialStuff = (true as false) || unpartial(null! as Stuff);
type UnpartialStuff = typeof unpartialStuff;
/**
 * Make all properties in T required
 */
type Required<T> = {
    [P in keyof T]-?: T[P];
};