logo
Tags down

shadow

Keys that sometimes exist on a typescript object depending on parameters


By : m.frazier
Date : July 31 2020, 06:00 AM
it fixes the issue I'm going to leave the implementation of getUser() us you, as well as convincing the compiler that your implementation meets the type definition. That is, I'm acting like getUser() is out in pure JavaScript land, and I'm just coming up with its type declaration so that the compiler can correctly handle calls to it.
First, the compiler needs some way of knowing about the mapping between arguments to getUser() and which sets of User keys they pick out. Something like this, given your example:
code :
interface KeyMap {
    purchases: "purchases",
    network: "friends" | "friendsOfFriends"
}
type UserType<K extends keyof KeyMap> =
    User & Pick<Required<User>, KeyMap[K]> extends 
    infer O ? { [P in keyof O]: O[P] } : never;
declare function getUser<K extends keyof KeyMap>(keys: K[]): UserType<K>;
const user = getUser([]);
/* const user: {
    id: number;
    purchases?: Purchase[] | undefined;
    friends?: Friend[] | undefined;
    friendsOfFriends?: Friend[] | undefined;
} */

const userWithPurchases = getUser(['purchases']);
/* const userWithPurchases: {
    id: number;
    purchases: Purchase[];
    friends?: Friend[] | undefined;
    friendsOfFriends?: Friend[] | undefined;
} */

const userWithNetwork = getUser(['network']);
/* const userWithNetwork: {
    id: number;
    purchases?: Purchase[] | undefined;
    friends: Friend[];
    friendsOfFriends: Friend[];
} */

const userWithEverything = getUser(['purchases', 'network']);
/* const userWithEverything: {
    id: number;
    purchases: Purchase[];
    friends: Friend[];
    friendsOfFriends: Friend[];
} */
type RequiredKeys<T> = { [K in keyof T]-?: {} extends Pick<T, K> ? never : K }[keyof T];

type UserType<K extends keyof KeyMap> =
    Pick<User, RequiredKeys<User>> & Pick<Required<User>, KeyMap[K]> extends
    infer O ? { [P in keyof O]: O[P] } : never;

declare function getUser<K extends keyof KeyMap>(keys: K[]): UserType<K>;


const user = getUser([]);
/* const user: {
    id: number;
} */

const userWithPurchases = getUser(['purchases']);
/* const userWithPurchases: {
    id: number;
    purchases: Purchase[];
} */

const userWithNetwork = getUser(['network']);
/* const userWithNetwork: {
    id: number;
    friends: Friend[];
    friendsOfFriends: Friend[];
} */

const userWithEverything = getUser(['purchases', 'network']);
/* const userWithEverything: {
    id: number;
    purchases: Purchase[];
    friends: Friend[];
    friendsOfFriends: Friend[];
} */


Share : facebook icon twitter icon

Can I use TypeScript to enforce an object's values depending on its keys?


By : user1394830
Date : March 29 2020, 07:55 AM
should help you out You can do this if you take advantage of the inference behavior of functions. We can create a function with a generic parameter to represent the union of string literal types and let the compiler figure out what that type is, which it will do.
code :
type Filter<ID extends string> = {
    display: string
    id: ID
    argType: 'string' | 'number' | 'date' | 'none'
}

type FilterMap<IDS extends string> = { [ID in IDS]: Filter<ID> }


function createFilterMap<T extends string>(fm: FilterMap<T>) {
    return fm
}

// Will be of type FilterMap<"foo" | "bar">
let x = createFilterMap({ 
    foo: { display: 'Foo', id: 'foo', argType: 'string' },
    bar: { display: 'Bar', id: 'bar', argType: 'string' },
})

Type an object with optional keys, but non-null value for keys that exist


By : RM13
Date : March 29 2020, 07:55 AM
I wish this helpful for you As mentioned in the comments, TypeScript doesn't do a great job of distinguishing missing properties from undefined properties. That's at least somewhat reasonable, since when you read a missing property from an object in JavaScript you will get undefined (and not an error). And before the --strictNullChecks compiler option was introduced in TypeScript 2.0, TypeScript did a very bad job of distinguishing missing/undefined properties from present/defined properties. This was mostly addressed by --strictNullChecks but a few issues linger.
One of the places that this issue still shows up is in types with index signatures. Index signatures are just considered to be present. There is no way to say some keys are present and some keys are absent with an index signature. The optional index signature syntax you want is not part of the language. With --strictNullChecks turned on, the signature {[k: string]: SomeType} is saying that every single string-key property exists and is of type SomeType, but this is not actually enforced when you assign objects to it. The only truly type safe way to use index signatures is to add | undefined to the value type, like {[k: string]: SomeType | undefined}, but this ends up becoming very annoying to use in many circumstances, leading to people overusing non-null assertions, which doesn't help anyone. So it is the way it is.
code :
type Record<K extends keyof any, T> = {[P in K]: T};

Typescript parameters - a generic array of objects and array of object's keys (partial)


By : Mario K.
Date : March 29 2020, 07:55 AM
Does that help You will need an extra type parameter to capture the actual tuple of keys being passed in. You can them map this tuple to the corresponding property types in T. It all works out very nicely:
code :
type MapKeyTupleToProps<T, P extends [keyof T] | Array<keyof T>> = {
    [K in keyof P]: P[K] extends keyof T ? T[P[K]] : never
}
const m = {
    mapToCsvData: <T, P extends [keyof T] | Array<keyof T>>(data: T[], fields: P): MapKeyTupleToProps<T, P> => {
        return data.map((item: any) => {
            return fields.map(field => item[field]);
        }) as any;
    }
}

const data = [
    {"firstName": "Jane", "lastName": "Doe", age: 0},
    {"firstName": "John", "lastName": "Doe", age: 0}
]

let r = m.mapToCsvData(data, ["firstName", "lastName"]) // [string, string]
let r2 = m.mapToCsvData(data, ["firstName", "age"]) //[string, number]

Why does the forEach() method exist for object keys but not array keys?


By : user3072569
Date : March 29 2020, 07:55 AM
To fix the issue you can do This is because Array.keys is NOT the same as Object.keys.
Array.keys return an iterator (or, really an "Array Iterator"), it doesn't expose any array prototype because it does not return an array, though it can be looped:
code :
for (var elem of Array(3).keys()){
	console.log(elem);
}

// If you really want to use forEach...
[...Array(3).keys()].forEach(k => console.log('spread syntax -> ', k));

// Or using Array.from
Array.from(Array(3).keys()).forEach(k => console.log('Array.from ->', k));

Typescript: Object with keys' types conditioned by other keys of the same object


By : linoxydable
Date : March 29 2020, 07:55 AM
around this issue You can leverage distributive conditional types to get type similar to Approach1 autogenerated:
code :
type MapToFieldValue<T, K = keyof T> = K extends keyof T ? { field: K, value: T[K] } : never;

const foo: MapToFieldValue<ISessionSpecific> = { field: 'address', value: 0 } // Expect error;
type ManualMap = {
    field: "students";
    value: number[] | undefined;
} | {
    field: "subject";
    value: number | undefined;
} | {
    field: "address";
    value: string | undefined;
} | {
    field: "duration";
    value: string[] | undefined;
} | {
    field: 'date';
    value: Date | undefined;
}
type MapToFieldValue<T> = { [K in keyof T]: { field: K, value: T[K] } }[keyof T]
Related Posts Related Posts :
  • Transform class to class/object (Entity to DTO) in TypeScript and NestS
  • Typescript create an object based on interface name?
  • Generic Return Type of function based on Input object fields
  • Typescript Assertion Signatures and Promises
  • cannot use import statement for scss files with typescript
  • TypeScript recursive type with particular depth
  • Why add a preceding vertical bar (|) to a union type literal in typescript?
  • Typescript Function with Generic Return Type
  • Dynamic tabs using angular 6
  • How do you declare a value constrained type?
  • NestJs can't resolve dependencies, why?
  • How to set a given table cell in Vue.js
  • Typescript flexible types
  • use Type at DynamoDB Output
  • How to use a variable value as placeholder in Vue with typescript
  • TypeScript Advanced Types - A problem with Unreachable error inside generic function
  • How should I do an Enum comparison in typescript
  • Typescript: type one parameter based on the other
  • Typescript Private or protected member 'something' cannot be accessed on a type parameter
  • Typescript - Class instance which implements generic type
  • Unable to infer type when returning a function
  • shadow
    Privacy Policy - Terms - Contact Us © voile276.org