【问题标题】:typescript restrict count of object's properties打字稿限制对象属性的计数
【发布时间】:2017-01-04 12:49:53
【问题描述】:

是否可以限制对象属性的数量,比如说我想限制对象只有一个字符串属性(任何名称),我可以这样做:

{[index: string]: any}

限制属性的类型,但可以限制属性的数量吗?

【问题讨论】:

    标签: typescript


    【解决方案1】:

    很可能没有。我想到的最好的解决方案是用你的自定义类包装一个Object(或Map),方法是set(key: string, val: any)和get(key: string),在某些情况下不允许向基础集合添加新项目。

    【讨论】:

      【解决方案2】:

      因为this question已被标记为与此重复,所以让我在这里回答。

      检查类型是否为联合

      /**
       * @see https://stackoverflow.com/questions/53953814/typescript-check-if-a-type-is-a-union/53955431
       */
      type IsSingleton<T> =
        [T] extends [UnionToIntersection<T>]
          ? true
          : false
      
      /**
       * @author https://stackoverflow.com/users/2887218/jcalz
       * @see https://stackoverflow.com/a/50375286/10325032
       */
      type UnionToIntersection<Union> =
        (Union extends any
          ? (argument: Union) => void
          : never
        ) extends (argument: infer Intersection) => void
          ? Intersection
        : never;
      

      只允许单例类型

      type SingletonOnly<T> =
        IsSingleton<T> extends true
          ? T
          : never
      

      限制函数只接受单例类型

      declare function foo<K extends string>(s: SingletonOnly<K>): void
      
      declare const singleton: 'foo';
      foo(singleton);
      
      declare const union: "foo" | "bar";
      foo(union); // Compile-time error
      

      TypeScript Playground

      【讨论】:

        【解决方案3】:

        这个问题在 Stackoverflow 上有很多答案(包括 this detailed one),但没有一个适合我的情况,这与此处发布的类似。

        问题

        我有一个接受对象的函数。如果传递的对象没有确切的一个键,我希望它抛出 Compilation Error (Typescript)。例如

        f({}); // Must error here, as it has less than one key!
        f({ x: 5 });
        f({ x: 5, y : 6 }); // Must error here, as it has more than one key!
        

        解决方案

        使用流行的UnionToIntersection和IsUnion,通过以下实用函数实现。

        type SingleKey<T> = IsUnion<keyof T> extends true ? never : {} extends T ? never : T;
        

        完整代码:

        // From https://stackoverflow.com/a/50375286
        type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never;
        
        // From: https://stackoverflow.com/a/53955431
        type IsUnion<T> = [T] extends [UnionToIntersection<T>] ? false : true;
        
        // Here we come!
        type SingleKey<T> = IsUnion<keyof T> extends true ? never : {} extends T ? never : T;
        
        // Usage:
        function f<T extends Record<string, any>>(obj: SingleKey<T>) {
            console.log({ obj });
        }
        
        f({}); // errors here!
        f({ x: 5 });
        f({ x: 5, y : 6 }); // errors here!
        

        Playground Link

        【讨论】:

        • Broken Playground 链接,您现在可以找到它here
        • 感谢@Stanislas。更新了链接
        猜你喜欢
        • 2018-07-27
        • 2018-12-31
        • 1970-01-01
        • 1970-01-01
        • 2021-11-08
        • 2019-07-28
        • 2019-10-03
        • 2020-12-17
        • 1970-01-01
        相关资源
        最近更新 更多