Typescript 扩展“记录”<;字符串,字符串[]>;`拥有不同类型的财产
在Typescript中,以下内容似乎可以完成所需类型的创建:Typescript 扩展“记录”<;字符串,字符串[]>;`拥有不同类型的财产,typescript,Typescript,在Typescript中,以下内容似乎可以完成所需类型的创建: interface RecordX extends Record<string, string[]> { id: string } 但每一个似乎都会导致错误 这感觉很普通,很明显,但我找不到一个例子或参考 如果未将其用于类,则可以使用类型对其进行描述: type RecordWithID = Record<string, string[]> & { id: string } let x:
interface RecordX extends Record<string, string[]> {
id: string
}
但每一个似乎都会导致错误
这感觉很普通,很明显,但我找不到一个例子或参考
如果未将其用于
类
,则可以使用类型
对其进行描述:
type RecordWithID = Record<string, string[]> & {
id: string
}
let x: RecordWithID = {} as any
x.id = 'abc'
x.abc = ['some-string']
键入RecordWithID=Record&{
id:字符串
}
设x:RecordWithID={}为任意
x、 id='abc'
x、 abc=['some-string']
从官方角度来看,你不可能实现你想要的:
而字符串索引签名是描述
“字典”模式,它们还强制所有属性匹配
它们的返回类型。这是因为字符串索引声明
obj.property也可以作为obj[“property”]提供。在下面
例如,名称的类型与字符串索引的类型不匹配,并且
类型检查器出现错误:
interface NumberDictionary {
[index: string]: number;
length: number; // ok, length is a number
name: string; // error, the type of 'name' is not a subtype of the indexer
}
然而,根据这一点,从索引签名中排除某些属性在一种情况下是可能的:当您想要对声明的变量建模时。我正在从网站上复制整个部分
有时需要将属性组合到索引签名中。
不建议这样做,您应该使用嵌套索引签名
上面提到的模式。但是,如果您正在建模现有的
JavaScript您可以使用交叉点类型绕过它。这个
下面显示了一个您将遇到的错误示例
使用交叉点:
type FieldState = {
value: string
}
type FormState = {
isValid: boolean // Error: Does not conform to the index signature
[fieldName: string]: FieldState
}
以下是使用交叉点类型的解决方法:
type FieldState = {
value: string
}
type FormState =
{ isValid: boolean }
& { [fieldName: string]: FieldState }
请注意,即使您可以将其声明为现有JavaScript建模,
无法使用TypeScript创建此类对象:
type FieldState = {
value: string
}
type FormState =
{ isValid: boolean }
& { [fieldName: string]: FieldState }
// Use it for some JavaScript object you are gettting from somewhere
declare const foo:FormState;
const isValidBool = foo.isValid;
const somethingFieldState = foo['something'];
// Using it to create a TypeScript object will not work
const bar: FormState = { // Error `isValid` not assignable to `FieldState
isValid: false
}
最后,作为一种变通方法,如果合适的话,您可以创建一个嵌套接口(请查看的“设计模式:嵌套索引签名”部分,其中动态字段位于接口的属性中
interface RecordX {
id: string,
count: number,
set: Set<number>,
dynamicFields: {
[k: string]: string[]
}
}
接口记录x{
id:string,
计数:数字,
集:集,,
动态字段:{
[k:string]:字符串[]
}
}
佩德罗的答案100%正确,是我旅程的开始,谢谢
我想找到最简单的解决方法,并找到了一个解决方案:Object.assign()
。手动构造这些对象时,甚至在使用spread运算符时,可能作为带有本机JavaScript功能的TypeScript互操作,似乎都不会出现类型错误
将Object.assign()
包装在工厂函数中并与并行类型相结合对我来说很优雅,也许它对其他人有用
//类型为的工厂
//工厂使用Object.assign(),它不会出错,并返回交叉点类型
函数RecordX(
fixedProps:{id:string},
动态操作?:记录
) {
返回Object.assign({},dynamicrops,fixedProps);
}
//类型名称方便地与工厂重叠,并解析为:
//
//类型RecordX=记录&{
//id:字符串;
// }
类型RecordX=返回类型;
//用法
//标准使用
常量模型:RecordX=RecordX({id:'id-1'}{
foo:[a'],
});
//正确类型:string
const id=model.id;
//正确类型:字符串[]
const otherProp=model.otherProp;
//“字符串不可分配给字符串[]”的相应错误
常量model2:RecordX=RecordX({id:'id-2'}{
酒吧:“b”
});
Record
意味着id
属性(如果存在)必须是字符串[]
。您不能使用与之不匹配的内容对其进行扩展;您正在尝试创建一个异常,而不是扩展,并且TypeScript(尚未)没有作为一个具体的类型来支持它。如果您想知道如何做,您可能需要扩展您的用例。请确保您的代码是一个;现在与记录的名称冲突模糊了您的问题。@jcalz添加了更多的描述+M原因是当遇到问题时,TypeScript试图做更多的事情o对象文字。这样做是为了避免明显的错误。因此,如果在对象文字构造之后添加动态属性,它将起作用。-我遇到了一些问题,因此我更新了问题的更多细节,并(希望暂时)将其取消标记为正确的解决方案。
type FieldState = {
value: string
}
type FormState =
{ isValid: boolean }
& { [fieldName: string]: FieldState }
// Use it for some JavaScript object you are gettting from somewhere
declare const foo:FormState;
const isValidBool = foo.isValid;
const somethingFieldState = foo['something'];
// Using it to create a TypeScript object will not work
const bar: FormState = { // Error `isValid` not assignable to `FieldState
isValid: false
}
interface RecordX {
id: string,
count: number,
set: Set<number>,
dynamicFields: {
[k: string]: string[]
}
}