TypeScript在不使用[key:string]的情况下声明对象结构

时间:2020-01-24 00:43:27

标签: typescript

我正在使用具有以下结构的界面:

awk 'BEGIN{FS=OFS=","}!/dfg/{$2="00070"}1' file
abc,00070,india
dfg,78910,china
abc,00070,japan
abc,00070,australia

现在,我想创建一个允许任何键的对象,但是该值始终为interface IAsset { file: string, type: number } 类型:

IAsset

我通过实现一种新类型尝试了this answer中概述的方法:

const list = {
    bike: {
        file: "./meshes/bike.fbx",
        type: 0,
    },
    sky: {
        file: "./textures/sky.jpg",
        type: 1,
        style: "red" // <-- should yield error
    }
};

但是我不想使用字符串访问我的元素,例如type AssetList{[key: string], IAsset} ,因为那样的话我可以请求不存在的元素,例如list["bike"]而不会出错(而且,我也会丢失自动完成功能)。

如何告诉TypeScript该对象中的每个值应为list["apple"]类型,而没有基于字符串的访问器?

2 个答案:

答案 0 :(得分:2)

没有任何一种类型可以表示您要查找的内容:具有已知键的对象类型,其所有属性值均为AWSTemplateFormatVersion : '2010-09-09' Transform: AWS::Serverless-2016-10-31 Description: add docs directly from s3 Parameters: Environment: Type: String Default: staging DocumentMetadataBucketName: Type: String DocumentSourceBucketName: Type: String DocumentMetadataBucketArn: Type: String DocumentSourceBucketArn: Type: String Resources: UploaddirectFunction: Type: AWS::Serverless::Function Properties: FunctionName: !Sub leopro-uploaddirect-function-${Environment} Handler: uploaddirect.handler Runtime: nodejs10.x Timeout: 300 Role: !GetAtt UploaddirectExecutionRole.Arn Environment: Variables: DOCUMENT_METADATA_BUCKET: !Ref DocumentMetadataBucketName DOCUMENT_SOURCE_BUCKET: !Ref DocumentSourceBucketName CodeUri: . UploaddirectExecutionRole: Type: AWS::IAM::Role Properties: RoleName: !Sub leopro-uploaddirect-exec-role-${Environment} ManagedPolicyArns: - "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" Policies: - PolicyName: !Sub leopro-uploaddirect-access-s3-${Environment} PolicyDocument: Version: "2012-10-17" Statement: - Effect: "Allow" Action: - "s3:GetObject" - "s3:PutObject" Resource: 'arn:aws:s3:::*/*' Statement: - Effect: "Allow" Action: - "s3:*" Resource: '*' AssumeRolePolicyDocument: Version: "2012-10-17" Statement: - Effect: "Allow" Principal: Service: - "lambda.amazonaws.com" Action: - "sts:AssumeRole" UploaddirectBucket: Type: AWS::S3::Bucket Properties: BucketName: !Sub leopro-uploaddirect-dropbox-bucket-${Environment} NotificationConfiguration: LambdaConfigurations: - Event: 's3:ObjectCreated:*' Function: !GetAtt UploaddirectFunction.Arn UploaddirectBucketPolicy: Type: AWS::S3::BucketPolicy Properties: Bucket: !Ref UploaddirectBucket PolicyDocument: Statement: - Action: - "s3:GetObject" Effect: "Allow" Resource: !Sub "arn:aws:s3:::leopro-uploaddirect-dropbox-bucket-${Environment}/*" Principal: "*" InvokeFromS3Permission: Type: AWS::Lambda::Permission Properties: FunctionName: !GetAtt UploaddirectFunction.Arn Action: "lambda:InvokeFunction" Principal: "s3.amazonaws.com" SourceArn: !Join [ "", [ "arn:aws:s3:::", !Sub "leopro-uploaddirect-dropbox-bucket-${Environment}" ] ] 类型。但是,您可以根据键集IAsset将其表示为generic类型AssetList<K>,例如:

K

然后您可以编写type AssetList<K extends PropertyKey> = Record<K, IAsset>; ,但是假设您希望编译器为您推断键,则可以使用辅助函数代替类型注释:

const list: AssertList<"bike"|"sky"> = {...}

并像这样使用它:

const asAssetList = <K extends PropertyKey>(a: AssetList<K>) => a;

如果不注释掉const list = asAssetList({ bike: { file: "./meshes/bike.fbx", type: 0, }, sky: { file: "./textures/sky.jpg", type: 1, // style: "red" // excess property warning here } }); ,您会得到一个excess property warning的期望值。

然后style: "red"会确切记住它拥有的键:

list

好的,希望能有所帮助;祝你好运!

Playground link to code

答案 1 :(得分:0)

经过一番摸索,我发现Record方法有点令人费解,而且过于抽象,无法完全掌握。此外,将此变量导入其他文件需要一个怪异的Record<"bike"|"sky", IAsset>接口,每次我需要添加一个以上元素时,该接口都难以声明和更新。

相反,我只是创建了一个类,并将每个属性声明为其自己的IAsset类型。现在,我可以轻松地将AssetListClassAssetList一起导入其他文件。

interface IAsset {
    file: string,
    type: number
}

export class AssetListClass {
    bike: IAsset = {
        file: "meshes/bike.fbx",
        type: 0
    };
    sky: IAsset = {
        file: "./textures/sky.jpg",
        type: 1,
    }
}

export const AssetList = new AssetListClass();
相关问题