How to extend a TypeScript interface and unpartial it - javascript

I want to be able to do the following:
interface Partials {
readonly start?: number;
readonly end?: number;
}
interface NotPartials extends Partials /*incorporate Unpartialing somehow */ {
readonly somewhere: number;
}
Then, NotPartials would be:
readonly start: number;
readonly end: number;
readonly somewhere: number;
Notice how start and end are required now. Is this possible anyway?

Well, this is silly.
I think in TypeScript 2.8 this is possible:
interface Partials {
readonly start?: number;
readonly end?: number;
}
interface NotPartials extends Required<Partials> {
readonly somewhere: number;
}

Related

Get interface that can have multiple query responses in GraphQL

Currently in my GraphQL query, i can receive a single array response. But my response can be multiple arrays and there can be null in between of the response too depending on the input. Currenly if i have two inputs and suppose i'm getting an array for the first input and error for the second, it will throw an error. I need to fix that by showing null if error and returning the array if success. Here's what i have right now:
export const LookupUsers = gql`
query {
lookupUsers(ethAddresses: ["0x433232bC8C604d0308B71Defdgd1Da86"]) {
...User
}
}
fragment Identifiable on Node {
__typename
id
}
fragment User on User {
...Identifiable
ethAddress
firstName
lastName
}
`;
export interface Result {
readonly user: null | Array<null | User> ;
readonly lookupUsers: Array<null | LookupUsersType>;
}
export interface LookupPayload {
readonly payload: Array<string>;
}
export interface User extends Identifiable {
readonly ethAddress: string;
readonly emailAddress?: string;
readonly firstName?: string;
readonly lastName?: string;
}
export interface LookupUsersType extends Identifiable {
readonly ethAddress: string;
readonly emailAddress: string;
readonly firstName?: string;
readonly lastName?: string;
}
export interface Identifiable {
readonly __typename: string;
readonly id: string;
}
Where am i going wrong with this ?

How to use composition in Typegraphql

Im using typeorm and typegraphql to build an API and I would like to abstract out properties of an entity into separate files and then import them to clean up the file:
Example of current
#Entity()
#ObjectType()
export class Person extends BaseEntity {
#Field()
#Column()
name: string;
#Field()
#Column()
surname: string;
#Field()
#Column()
age: number;
#Field()
#Column()
email: string;
}
I would like to do something like this:
class Name {
#Field()
#Column()
name: string;
#Field()
#Column()
surname: string;
}
#Entity()
#ObjectType()
export class Person extends BaseEntity {
#Field()
#Column()
age: number;
#Field()
#Column()
email: string;
// then import the class here
...Name
}
Is there any way to do this without creating separate entities and tables?
Ended up using mixins to solve this because embedded entities doesn't work with both typeorm and typegraphql
export const WithName = <SubClass extends Constructor>(subClass?: SubClass) => {
#ObjectType({ isAbstract: true })
#InputType({ isAbstract: true })
class Mixin extends getFallbackClass(subClass) {
constructor(...args: any[]) {
super(...args);
}
#Field()
#Column()
first: string;
#Field()
#Column()
second: string;
}
return Mixin;
};
then using it like:
class Human extends WithName(class {}) {
}
This is only possible client side by using fragments https://www.apollographql.com/docs/react/data/fragments/
Perhaps you can use something like type inheritance perhaps by using this library https://github.com/nicolasdao/graphql-s2s
Check out this link for reference.

React Typescript interface

I get a problem when making an interface on Typescript!
export interface Content {
uuid?: string;
brand_id?: string;
brand_name?: string;
is_active?: boolean;
}
export interface Pageable {
sort?: Sort;
pageSize?: number;
pageNumber?: number;
offset?: number;
unpaged?: boolean;
paged?: boolean;
}
export interface Sort {
sorted?: boolean;
unsorted?: boolean;
empty?: boolean;
}
export interface BrandData {
content?: Content;
pageable?: Pageable;
numberOfElements?: number;
number?: number;
sort?: Sort;
size?: number;
first?: boolean;
last?: boolean;
empty?: boolean;
}
export interface BrandResponse {
readonly data?: BrandData[];
}
and then i want to get data in react component like this
const { brands } = useSelector((state: AppState) => state.catalogs.brands);
const [brandData, setBrandData] = React.useState(brands.data);
const [currentPage, setCurrentPage] = React.useState(brandData.pageable.pageNumber);
then the error exits like this
Property 'pageable' does not exist on type 'BrandData[]'.

TSX: Props type definition for a number input

In JSX/TSX syntax from react, all inputs seems to be define with the same props declaration which is InputHTMLAttributes:
interface InputHTMLAttributes<T> extends HTMLAttributes<T> {
accept?: string;
alt?: string;
autoComplete?: string;
autoFocus?: boolean;
capture?: boolean | string; // https://www.w3.org/TR/html-media-capture/#the-capture-attribute
checked?: boolean;
crossOrigin?: string;
disabled?: boolean;
form?: string;
formAction?: string;
formEncType?: string;
formMethod?: string;
formNoValidate?: boolean;
formTarget?: string;
height?: number | string;
list?: string;
max?: number | string;
maxLength?: number;
min?: number | string;
minLength?: number;
multiple?: boolean;
name?: string;
pattern?: string;
placeholder?: string;
readOnly?: boolean;
required?: boolean;
size?: number;
src?: string;
step?: number | string;
type?: string;
value?: string | ReadonlyArray<string> | number;
width?: number | string;
onChange?: ChangeEventHandler<T>;
}
I want to define a specific type for only an input of type number so that TypeScript complains if I use a checked or disabled prop on it:
<!-- invalid `checked` prop -->
<input type="number" step="any" min="0" max="100" value="22.33" checked={true} />
So is there already a type definition for that coming from React?
I know that I can just define it like the following but I would prefer to use an official source:
interface InputNumberProps {
type: 'number';
max?: number | string;
min?: number | string;
...
}
I think the simplest solution would be to wrap input into your own component and provide custom type definitions. As far as I know, there is nothing like that coming from official React types. This is done because HTML itself is not strongly typed and it is valid to do something like <input type="number" checked />
As for type definition something like that would suffice:
interface NumberInputProps {
type: "number"
value: number
min?: number
max?: number
}
interface TextInputProps {
type?: "text"
value: string
}
interface CheckboxInputProps {
type: "checkbox"
checked?: boolean
}
type InputProps = NumberInputProps | TextInputProps | CheckboxInputProps
const Input: React.FC<InputProps> = (props) => <input {...props} />
That is a lot of typings for sure (and this does not event include things like events, class names etc). Also, this requires even more JS code if you want to provide stronger types for something like number fields (converting strings into numbers etc.)
If you want to modify the original InputHTMLAttributes (which is a better solution than writing your own types from scratch) interface, overriding and/or omitting some of the fields there are helper types like Omit that would allow you to do so.
type InputProps = Omit<InputHTMLAttributes<HTMLInputElement>, "type" | "value" | "checked" | "min" | "max"> & (NumberInputProps | TextInputProps | CheckboxInputProps)
You can also split different input types into different components if you find writing too much logic in one component. Do whatever suits you
P.S. on the second note. This sounds like type over-engeneering
You can use and extends the official types:
export type InputProps = React.DetailedHTMLProps<
React.InputHTMLAttributes<HTMLInputElement>,
HTMLInputElement
>;
interface NumberInputProps extends Omit<InputProps, 'checked' | 'disabled'> {
value: number
}
Using this code you exclude checked and disabled properties and overrides value to allow only numbers instead string | ReadonlyArray | number

Extending Interface/types in typescript

I have extended my FilterMetaData type to add a dynamic model which is different structure for different entities but somehow typescript not recognizing my object properties. I might be missing something here.
Interfaces
export type FilterMetaData<T extends {}> = T & {
filterCriteriaID: number;
filterCriteriaName?: string;
isDefaultSelected?: boolean;
isExpanded?: boolean;
}
export interface DateRange {
data?: DateRangeData;
}
export interface DateRangeData {
min?: Date;
max?: Date;
}
export interface Range {
data?: RangeData;
}
export interface RangeData {
currency?: string;
timePeriod?: string;
min?: number;
max?: number;
step?: number;
}
export interface Select {
data?: SelectData[];
}
export interface SelectData {
id?: number;
name?: string;
isSelected?:boolean|false;
parentID?: number | null;
parentName?: string;
}
Implementation in class
helper<T1 extends FilterMetaData<T2>>(filter) {
this.selectedFilterService.getAppliedFilterMasterData<T1>(filter)
.pipe(takeUntil(this.unsubscribe$))
.subscribe((filterData: T1) => {
if (filter.isDefaultSelected) {
filterData.isExpanded = false;
filterData.data.forEach((data) => data.isSelected = false);
this.selectedFilters.result.select.push(filterData);
this.loadComponent(new FilterComponentType(SelectComponent, filterData));
} else {
this.removeComponent(filter);
}
}, err => {
this.toastrService.error(err);
})
}
Invoking Function with type args like this:--
this.helper<FilterMetaData<Select>>(filter);

Categories

Resources